diff --git a/.github/workflows/bin-solr-test.yml b/.github/workflows/bin-solr-test.yml index a0a33ccc51a..126e8d62293 100644 --- a/.github/workflows/bin-solr-test.yml +++ b/.github/workflows/bin-solr-test.yml @@ -24,11 +24,11 @@ jobs: steps: # Setup - uses: actions/checkout@v4 - - name: Set up JDK 11 + - name: Set up JDK uses: actions/setup-java@v4 with: distribution: 'temurin' - java-version: 11 + java-version: 21 java-package: jdk - name: Setup Gradle uses: gradle/actions/setup-gradle@v4 diff --git a/.github/workflows/docker-test.yml b/.github/workflows/docker-test.yml index 0b00a6ab308..d8593613ca6 100644 --- a/.github/workflows/docker-test.yml +++ b/.github/workflows/docker-test.yml @@ -26,11 +26,11 @@ jobs: steps: # Setup - uses: actions/checkout@v4 - - name: Set up JDK 11 + - name: Set up JDK 21 uses: actions/setup-java@v4 with: distribution: 'temurin' - java-version: 11 + java-version: 21 java-package: jdk - name: Setup Gradle uses: gradle/actions/setup-gradle@v4 diff --git a/.github/workflows/gradle-precommit.yml b/.github/workflows/gradle-precommit.yml index dcc55ead323..67c1506ad0a 100644 --- a/.github/workflows/gradle-precommit.yml +++ b/.github/workflows/gradle-precommit.yml @@ -8,7 +8,7 @@ on: jobs: test: - name: gradle check w/ Java 11 + name: gradle check runs-on: ubuntu-latest @@ -19,11 +19,11 @@ jobs: # Setup - uses: actions/checkout@v4 - - name: Set up JDK 11 + - name: Set up JDK uses: actions/setup-java@v4 with: distribution: 'temurin' - java-version: 11 + java-version: 21 java-package: jdk - name: Setup Gradle diff --git a/.github/workflows/solrj-test.yml b/.github/workflows/solrj-test.yml index 1a0f6bfebde..3eb9bb4f5f6 100644 --- a/.github/workflows/solrj-test.yml +++ b/.github/workflows/solrj-test.yml @@ -21,11 +21,11 @@ jobs: steps: # Setup - uses: actions/checkout@v4 - - name: Set up JDK 11 + - name: Set up JDK 21 uses: actions/setup-java@v4 with: distribution: 'temurin' - java-version: 11 + java-version: 21 java-package: jdk - name: Setup Gradle uses: gradle/actions/setup-gradle@v4 diff --git a/README.md b/README.md index 920a4fa3005..24d419bd472 100644 --- a/README.md +++ b/README.md @@ -22,7 +22,7 @@ Solr is the blazing-fast, open source, multi-modal search platform built on [Apa It powers full-text, vector, and geospatial search at many of the world's largest organizations. [![Build Status](https://ci-builds.apache.org/job/Solr/job/Solr-Artifacts-main/badge/icon?subject=Solr%20Artifacts)](https://ci-builds.apache.org/job/Solr/job/Solr-Artifacts-main/) -[![Build Status](https://ci-builds.apache.org/job/Solr/job/Solr-Check-main/badge/icon?subject=Solr%20Check)](https://ci-builds.apache.org/job/Solr/job/Solr-Check-main/) +[![Build Status](https://ci-builds.apache.org/job/Solr/job/Solr-Lint-main/badge/icon?subject=Solr%20Lint)](https://ci-builds.apache.org/job/Solr/job/Solr-Lint-main/) For a complete description of the Solr project, team composition, source code repositories, and other details, please see the Solr web site at @@ -94,7 +94,7 @@ Solr uses [Gradle](https://gradle.org/) for its build system. Here are some usef ``` cd ./solr/packaging/build/dev -bin/solr start -c +bin/solr start ``` - Open a web browser and go to http://localhost:8983/solr/ to access the Solr Admin interface. You can also use the `bin/solr` script to create and manage Solr collections. For example use the `bin/solr post` tool to index some sample data. @@ -108,4 +108,3 @@ To get involved in the developer community: - Slack: `#solr-dev` in the `the-asf` organization. Sign up at https://the-asf.slack.com/messages/CE70MDPMF - [Issue Tracker (JIRA)](https://issues.apache.org/jira/browse/SOLR) - IRC: `#solr-dev` on [libera.chat](https://web.libera.chat/?channels=#solr-dev) - diff --git a/build-tools/build-infra/src/main/java/org/apache/lucene/gradle/WrapperDownloader.java b/build-tools/build-infra/src/main/java/org/apache/lucene/gradle/WrapperDownloader.java index f7e07eb164a..adb8f3eaf07 100644 --- a/build-tools/build-infra/src/main/java/org/apache/lucene/gradle/WrapperDownloader.java +++ b/build-tools/build-infra/src/main/java/org/apache/lucene/gradle/WrapperDownloader.java @@ -22,7 +22,7 @@ import java.io.InputStream; import java.io.OutputStream; import java.net.HttpURLConnection; -import java.net.URL; +import java.net.URI; import java.nio.charset.StandardCharsets; import java.nio.file.Files; import java.nio.file.Path; @@ -54,10 +54,10 @@ public static void main(String[] args) { } public static void checkVersion() { - int major = Runtime.getRuntime().version().feature(); - if (major < 11 || major > 21) { + int major = Runtime.version().feature(); + if (major < 21 || major > 23) { throw new IllegalStateException( - "java version must be between 11 and 21, your version: " + major); + "java version must be between 21 and 23, your version: " + major); } } @@ -89,12 +89,12 @@ public void run(Path destination) throws IOException, NoSuchAlgorithmException { } } - URL url = - new URL( + URI uri = + URI.create( "https://raw.githubusercontent.com/gradle/gradle/v" + wrapperVersion + "/gradle/wrapper/gradle-wrapper.jar"); - System.err.println("Downloading gradle-wrapper.jar from " + url); + System.err.println("Downloading gradle-wrapper.jar from " + uri); // Zero-copy save the jar to a temp file Path temp = Files.createTempFile(destination.getParent(), ".gradle-wrapper", ".tmp"); @@ -103,7 +103,7 @@ public void run(Path destination) throws IOException, NoSuchAlgorithmException { int retryDelay = 30; HttpURLConnection connection; while (true) { - connection = (HttpURLConnection) url.openConnection(); + connection = (HttpURLConnection) uri.toURL().openConnection(); try { connection.connect(); } catch (IOException e) { diff --git a/build-tools/scriptDepVersions.gradle b/build-tools/scriptDepVersions.gradle index 2a83896148e..329905331a9 100644 --- a/build-tools/scriptDepVersions.gradle +++ b/build-tools/scriptDepVersions.gradle @@ -21,10 +21,11 @@ ext { scriptDepVersions = [ - "min-java-version": "11", + "min-java-version": "21", + "min-solrj-java-version" : "17", "apache-rat": "0.15", "commons-codec": "1.16.0", - "ecj": "3.33.0", + "ecj": "3.39.0", "javacc": "7.0.12", "jgit": "6.7.0.202309050840-r", "flexmark": "0.64.8", diff --git a/build.gradle b/build.gradle index 3cecb1aa0cd..13065fcfc8f 100644 --- a/build.gradle +++ b/build.gradle @@ -35,7 +35,7 @@ apply from: file('build-tools/scriptDepVersions.gradle') // Declare default Java versions for the entire project and for SolrJ separately rootProject.ext.minJavaVersionDefault = JavaVersion.toVersion(scriptDepVersions['min-java-version']) -rootProject.ext.minJavaVersionSolrJ = JavaVersion.toVersion(scriptDepVersions['min-java-version']) +rootProject.ext.minJavaVersionSolrJ = JavaVersion.toVersion(scriptDepVersions['min-solrj-java-version']) apply from: file('gradle/globals.gradle') diff --git a/dev-docs/apis.adoc b/dev-docs/apis.adoc index 9e710f7e0a4..fa0565a14d9 100644 --- a/dev-docs/apis.adoc +++ b/dev-docs/apis.adoc @@ -81,4 +81,3 @@ A good example for each of these steps can be seen in Solr's v2 "add-replica-pro While we've settled on JAX-RS as our framework for defining v2 APIs going forward, Solr still retains many v2 APIs that were written using an older homegrown framework. This framework defines APIs using annotations (e.g. `@EndPoint`) similar to those used by JAX-RS, but lacks the full range of features and 3rd-party tooling. We're in the process of migrating these API definitions to JAX-RS and hope to remove all support for this legacy framework in a future release. - diff --git a/dev-docs/asf-jenkins.adoc b/dev-docs/asf-jenkins.adoc new file mode 100644 index 00000000000..b3c59b6fd9e --- /dev/null +++ b/dev-docs/asf-jenkins.adoc @@ -0,0 +1,73 @@ += ASF Jenkins Setup +:toc: left + +The Solr project uses a Jenkins instance provided by the Apache Software Foundation ("ASF") for running tests, validation, etc. + +This file aims to document our [ASF Jenkins](https://ci-builds.apache.org/job/Solr/) usage and administration, to prevent it from becoming "tribal knowledge" understood by just a few. + +== Jobs + +We run a number of jobs on Jenkins, each validating an overlapping set of concerns: + +* `Solr-Artifacts-*` - daily jobs that run `./gradlew assemble` to ensure that build artifacts (except docker images) can be created successfully +* `Solr-Lint-*` - daily jobs that run static analysis (i.e. `precommit` and `check -x test`) on a branch +* `Solr-Test-*` - "hourly" jobs that run all (non-integration) tests (i.e. `./gradlew test`) +* `Solr-TestIntegration-*` - daily jobs that run project integration tests (i.e. `./gradlew integrationTests`) +* `Solr-Docker-Nightly-*` - daily jobs that `./gradlew testDocker dockerPush` to validate docker image packaging. Snapshot images are pushed to hub.docker.com +* `Solr-reference-guide-*` - daily jobs that build the Solr reference guide via `./gradlew checkSite` and push the resulting artifact to the staging/preview site `nightlies.apache.org` +* `Solr-Smoketest-*` - daily jobs that produce a snapshot release (via the `assembleRelease` task) and run the release smoketester + +Most jobs that validate particular build artifacts are run "daily", which is sufficient to prevent any large breaks from creeping into the build. +On the other hand, jobs that run tests are triggered "hourly" in order to squeeze as many test runs as possible out of our Jenkins hardware. +This is a necessary consequence of Solr's heavy use of randomization in its test-suite. +"Hourly" scheduling ensures that a test run is either currently running or in the build queue at all times, and enables us to get the maximum data points from our hardware. + +== Jenkins Agents + +All Solr jobs run on Jenkins agents marked with the 'solr' label. +Currently, this maps to two Jenkins agents: + +* `lucene-solr-1` - available at lucene1-us-west.apache.org +* `lucene-solr-2` - available (confusingly) at lucene-us-west.apache.org + +These agents are "project-specific" VMs shared by the Lucene and Solr projects. +That is: they are VMs requested by a project for their exclusive use. +(INFRA policy appears to be that each Apache project may request 1 dedicated VM; it's unclear how Solr ended up with 2.) + +Maintenance of these agent VMs falls into a bit of a gray area. +INFRA will still intervene when asked: to reboot nodes, to deploy OS upgrades, etc. +But some burden also falls on Lucene and Solr as project teams to monitor the the VMs and keep them healthy. + +=== Accessing Jenkins Agents + +With a few steps, Solr committers can access our project's Jenkins agent VMs via SSH to troubleshoot and resolve issues. + +1. Ensure your account on id.apache.org has an SSH key associated with it. +2. Ask INFRA to give your Apache ID SSH access to these boxes. (See [this JIRA ticket](https://issues.apache.org/jira/browse/INFRA-3682) for an example.) +3. SSH into the desired box with: `ssh @$HOSTNAME` (where `$HOSTNAME` is either `lucene1-us-west.apache.org` or `lucene-us-west.apache.org`) + +Often, SSH access on the boxes is not sufficient, and administrators require "root" access to diagnose and solve problems. +Sudo/su priveleges can be accessed via a one-time pad ("OTP") challenge, managed by the "Orthrus PAM" module. +Users in need of root access can perform the following steps: + +1. Open the ASF's [OTP Generator Tool](https://selfserve.apache.org/otp-calculator.html) in your browser of choice +2. Run `ortpasswd` on the machine. This will print out a OTP "challenge" (e.g. `otp-md5 497 lu6126`) and provide a password prompt. This password prompt should be given a OTP password, generated in steps 3-5 below. +3. Copy the "challenge" from the previous step into the relevant field on the "OTP Generator Tool" form. +4. Choose a password to use for OTP Challenges (or recall one you've used in the past), and type this into the relevant field on the "OTP Generator Tool" form. +5. Click "Compute", and copy the first line from the "Response" box into your SSH session's password prompt. You're now established in the "Orthrus PAM" system. +6. Run a command requesting `su` escalation (e.g. `sudo su -`). This should print another "challenge" and password prompt. Repeat steps 3-5. + +If this fails at any point, open a ticket with INFRA. +You may need to be added to the 'sudoers' file for the VM(s) in question. + +=== Known Jenkins Issues + +One recurring problem with the Jenkins agents is that they periodically run out of disk-space. +Usually this happens when enough "workspaces" are orphaned or left behind, consuming all of the agent's disk space. + +Solr Jenkins jobs are currently configured to clean up the previous workspace at the *start* of the subsequent run. +This avoids orphans in the common case but leaves workspaces behind any time a job is renamed or deleted (as happens during the Solr release process). + +Luckily, this has an easy fix: SSH into the agent VM and delete any workspaces no longer needed in `/home/jenkins/jenkins-slave/workspace/Solr`. +Any workspace that doesn't correspond to a [currently existing job](https://ci-builds.apache.org/job/Solr/) can be safely deleted. +(It may also be worth comparing the Lucene workspaces in `/home/jenkins/jenkins-slave/workspace/Lucene` to [that project's list of jobs](https://ci-builds.apache.org/job/Lucene/).) diff --git a/dev-docs/solr-source-code.adoc b/dev-docs/solr-source-code.adoc index ad73858a478..5874a2e06ec 100644 --- a/dev-docs/solr-source-code.adoc +++ b/dev-docs/solr-source-code.adoc @@ -2,10 +2,10 @@ ## Building Solr from Source -Download the Java 11 JDK (Java Development Kit) or later. +Download the Java 21 JDK (Java Development Kit) or later. We recommend the OpenJDK distribution Eclipse Temurin available from https://adoptium.net/. You will need the JDK installed, and the $JAVA_HOME/bin (Windows: %JAVA_HOME%\bin) folder included on your command path. -To test this, issue a "java -version" command from your shell (command prompt) and verify that the Java version is 11 or later. +To test this, issue a "java -version" command from your shell (command prompt) and verify that the Java version is 21 or later. See the xref:jvms.adoc[JVM developer doc] for more information on Gradle and JVMs. Clone the latest Apache Solr source code directly from the Git repository: . diff --git a/dev-tools/scripts/releaseWizard.yaml b/dev-tools/scripts/releaseWizard.yaml index 6b1a84041de..a1ccdc5cf44 100644 --- a/dev-tools/scripts/releaseWizard.yaml +++ b/dev-tools/scripts/releaseWizard.yaml @@ -1864,16 +1864,9 @@ groups: root_folder: '{{ git_checkout_folder }}' commands_text: | Run these commands to delete proposed versions from distribution directory. - Note, as long as we have some releases (7.x, 8.x) in Lucene dist repo and other - releases (9.0 ->) in the Solr dist repo, we may need to delete two places. - + WARNING: Validate that the proposal is correct! commands: - - !Command - cmd: | - svn rm -m "Stop publishing old Solr releases"{% for ver in mirrored_versions_to_delete %} https://dist.apache.org/repos/dist/release/lucene/solr/{{ ver }}{% endfor %} - logfile: svn-rm-solr.log - comment: Delete from Lucene dist area - !Command cmd: | svn rm -m "Stop publishing old Solr releases"{% for ver in mirrored_versions_to_delete %} https://dist.apache.org/repos/dist/release/solr/solr/{{ ver }}{% endfor %} diff --git a/dev-tools/scripts/smokeTestRelease.py b/dev-tools/scripts/smokeTestRelease.py index 97ca684ff56..acfa109f2fc 100755 --- a/dev-tools/scripts/smokeTestRelease.py +++ b/dev-tools/scripts/smokeTestRelease.py @@ -774,8 +774,6 @@ def testSolrExample(binaryDistPath, javaPath): raise RuntimeError('Failed to run the techproducts example, check log for previous errors.') os.chdir('example') - print(' test utf8...') - run('sh ./exampledocs/test_utf8.sh http://localhost:8983/solr/techproducts', 'utf8.log') print(' run query...') s = load('http://localhost:8983/solr/techproducts/select/?q=video') if s.find('"numFound":3,') == -1: diff --git a/gradle/documentation/render-javadoc.gradle b/gradle/documentation/render-javadoc.gradle index bd90ad35426..6c637e540df 100644 --- a/gradle/documentation/render-javadoc.gradle +++ b/gradle/documentation/render-javadoc.gradle @@ -32,7 +32,7 @@ allprojects { missingdoclet "org.apache.solr.tools:missing-doclet" } - ext { + project.ext { relativeDocPath = project.path.replaceFirst(/:\w+:/, "").replace(':', '/') } diff --git a/gradle/globals.gradle b/gradle/globals.gradle index 30eaa0857ab..d8a99de69c2 100644 --- a/gradle/globals.gradle +++ b/gradle/globals.gradle @@ -37,7 +37,7 @@ allprojects { // so :solr:core will have solr-core.jar, etc. project.archivesBaseName = project.path.replaceAll("^:", "").replace(':', '-') - ext { + project.ext { // Utility method to support passing overrides via -P or -D. propertyOrDefault = { propName, defValue -> def result @@ -173,5 +173,6 @@ allprojects { // Assign different java version for client-side modules 'api' and 'solrj*' var isSolrJ = project.name.matches("^(solrj.*|api)\$") minJavaVersion = isSolrJ ? rootProject.minJavaVersionSolrJ : rootProject.minJavaVersionDefault + minJavaTestVersion = rootProject.minJavaVersionDefault } } diff --git a/gradle/java/javac.gradle b/gradle/java/javac.gradle index 53320cc01c0..ec33f977c64 100644 --- a/gradle/java/javac.gradle +++ b/gradle/java/javac.gradle @@ -19,14 +19,19 @@ allprojects { plugins.withType(JavaPlugin) { - sourceCompatibility = project.minJavaVersion - targetCompatibility = project.minJavaVersion - - // Use 'release' flag instead of 'source' and 'target' - tasks.withType(JavaCompile) { - options.compilerArgs += ["--release", project.minJavaVersion.toString()] - } - + // Use 'release' flag instead of 'source' and 'target' + tasks.withType(JavaCompile) { + compileTestJava { + sourceCompatibility = project.minJavaTestVersion + targetCompatibility = project.minJavaTestVersion + options.compilerArgs += ["--release", project.minJavaTestVersion.toString()] + } + compileJava { + sourceCompatibility = project.minJavaVersion + targetCompatibility = project.minJavaVersion + options.compilerArgs += ["--release", project.minJavaVersion.toString()] + } + } // Configure warnings. tasks.withType(JavaCompile) { options.encoding = "UTF-8" @@ -51,22 +56,12 @@ allprojects { "-Xdoclint:all/protected", "-Xdoclint:-missing", "-Xdoclint:-accessibility", + "-Xlint:synchronization", + "-Xlint:text-blocks", "-proc:none", // proc:none was added because of LOG4J2-1925 / JDK-8186647 + "-Xlint:removal" ] - // enable some warnings only relevant to newer language features - if (rootProject.runtimeJavaVersion >= JavaVersion.VERSION_15) { - options.compilerArgs += [ - "-Xlint:text-blocks", - ] - } - - if (rootProject.runtimeJavaVersion >= JavaVersion.VERSION_16) { - options.compilerArgs += [ - "-Xlint:synchronization", - ] - } - if (propertyOrDefault("javac.failOnWarnings", true).toBoolean()) { options.compilerArgs += "-Werror" } diff --git a/gradle/node.gradle b/gradle/node.gradle index 3da3a51d40e..ff8404c2db2 100644 --- a/gradle/node.gradle +++ b/gradle/node.gradle @@ -34,7 +34,7 @@ configure([project(":solr:packaging"), project(":solr:solr-ref-guide"), project( } } - ext { + project.ext { rootNodeDir = "$rootDir/.gradle/node" nodeProjectDir = file("$rootNodeDir/$project.name") } diff --git a/gradle/solr/packaging.gradle b/gradle/solr/packaging.gradle index 11ffb560688..1b5325f908b 100644 --- a/gradle/solr/packaging.gradle +++ b/gradle/solr/packaging.gradle @@ -38,7 +38,7 @@ configure(allprojects.findAll {project -> project.path.startsWith(":solr:modules:") || project.path == ":solr:prometheus-exporter" || project.path == ":solr:cross-dc-manager" }) { plugins.withType(JavaPlugin) { - ext { + project.ext { packagingDir = file("${buildDir}/packaging") if (project.path.startsWith(":solr:prometheus-exporter") || project.path.startsWith(":solr:cross-dc-manager")) { deps = packagingDir diff --git a/gradle/template.gradle.properties b/gradle/template.gradle.properties index c52e3048a77..79b18753f43 100644 --- a/gradle/template.gradle.properties +++ b/gradle/template.gradle.properties @@ -49,6 +49,11 @@ # tests.minheapsize=512m # tests.jvmargs=-XX:+UseParallelGC -XX:TieredStopAtLevel=1 -XX:ActiveProcessorCount=1 # +# If you want tests to produce an html report (which intellij provides a clickable link for +# at the end of a failed build) set this to true, defaults to false to save a few seconds. +# +# tests.html=false +# ################# # Gradle Daemon # ################# @@ -98,5 +103,8 @@ org.gradle.workers.max=@MAX_WORKERS@ # Maximum number of test JVMs forked per test task. tests.jvms=@TEST_JVMS@ +# By default skip html generation +tests.html=false + # Disable auto JVM provisioning (we don't use toolchains yet but want no surprises). org.gradle.java.installations.auto-download=false diff --git a/gradle/testing/alternative-jdk-support.gradle b/gradle/testing/alternative-jdk-support.gradle index 72cdabdab4b..a1ff1b4b014 100644 --- a/gradle/testing/alternative-jdk-support.gradle +++ b/gradle/testing/alternative-jdk-support.gradle @@ -87,6 +87,6 @@ if (jvmGradle != jvmCurrent) { // Set up root project's properties. rootProject.ext.runtimeJavaHome = jvmCurrent.javaHome -rootProject.ext.runtimeJavaVersion = jvmDetector.getMetadata(new InstallationLocation(jvmCurrent.javaHome, "specific path")).getLanguageVersion() +rootProject.ext.runtimeJavaVersion = jvmDetector.getMetadata(InstallationLocation.userDefined(jvmCurrent.javaHome, "specific path")).getLanguageVersion() rootProject.ext.usesAltJvm = (jvmGradle != jvmCurrent); diff --git a/gradle/testing/beasting.gradle b/gradle/testing/beasting.gradle index 8934100ec10..67c20140ba8 100644 --- a/gradle/testing/beasting.gradle +++ b/gradle/testing/beasting.gradle @@ -27,7 +27,7 @@ def beastingMode = gradle.startParameter.taskNames.any{ name -> name == 'beast' allprojects { plugins.withType(JavaPlugin) { - ext { + project.ext { testOptions += [ [propName: 'tests.dups', value: 0, description: "Reiterate runs of entire test suites ('beast' task)."] ] diff --git a/gradle/testing/defaults-tests.gradle b/gradle/testing/defaults-tests.gradle index f0af07c81de..9241720e8c3 100644 --- a/gradle/testing/defaults-tests.gradle +++ b/gradle/testing/defaults-tests.gradle @@ -111,12 +111,6 @@ allprojects { ignoreFailures = resolvedTestOption("tests.haltonfailure").toBoolean() == false jvmArgs Commandline.translateCommandline(resolvedTestOption("tests.jvmargs")) - - // Up to JDK-15 we have to enforce --illegal-access=deny, because we want no code to access - // JDK internals; JDK-16 and later will default to deny, see https://openjdk.java.net/jeps/396: - if (rootProject.runtimeJavaVersion < JavaVersion.VERSION_16) { - jvmArgs '--illegal-access=deny' - } def loggingConfigFile = layout.projectDirectory.file("${resources}/logging.properties") def tempDir = layout.projectDirectory.dir(testsTmpDir.toString()) @@ -153,7 +147,7 @@ allprojects { } // Disable HTML report generation. The reports are big and slow to generate. - reports.html.required = false + reports.html.required = Boolean.parseBoolean(providers.gradleProperty("tests.html").getOrElse("false")) // Set up logging. testLogging { diff --git a/gradle/testing/profiling.gradle b/gradle/testing/profiling.gradle index ce9e7d43e03..8b1e5147efc 100644 --- a/gradle/testing/profiling.gradle +++ b/gradle/testing/profiling.gradle @@ -19,7 +19,7 @@ def recordings = files() allprojects { plugins.withType(JavaPlugin) { - ext { + project.ext { testOptions += [ [propName: 'tests.profile', value: false, description: "Enable java flight recorder profiling."] ] diff --git a/gradle/testing/randomization.gradle b/gradle/testing/randomization.gradle index 2b617b99aa8..183943a39e7 100644 --- a/gradle/testing/randomization.gradle +++ b/gradle/testing/randomization.gradle @@ -79,7 +79,7 @@ allprojects { // Configure test property defaults and their descriptions. allprojects { plugins.withType(JavaPlugin) { - ext { + project.ext { testOptions += [ // seed, repetition and amplification. [propName: 'tests.seed', value: { -> rootSeed }, description: "Sets the master randomization seed."], @@ -124,7 +124,7 @@ allprojects { // Add Solr-specific test configs settings. configure(allprojects.findAll {project -> project.path.startsWith(":solr") }) { plugins.withType(JavaPlugin) { - ext { + project.ext { testOptions += [ [propName: 'tests.src.home', value: null, description: "See SOLR-14023."], [propName: 'solr.tests.use.numeric.points', value: null, description: "Point implementation to use (true=numerics, false=trie)."], @@ -137,14 +137,14 @@ configure(allprojects.findAll {project -> project.path.startsWith(":solr") }) { allprojects { plugins.withType(JavaPlugin) { afterEvaluate { - ext.testOptionsResolved = testOptions.findAll { opt -> + project.ext.testOptionsResolved = testOptions.findAll { opt -> propertyOrDefault(opt.propName, opt.value) != null }.collectEntries { opt -> [(opt.propName): Objects.toString(resolvedTestOption(opt.propName))] } // Compute the "reproduce with" string. - ext.testOptionsForReproduceLine = testOptions.findAll { opt -> + project.ext.testOptionsForReproduceLine = testOptions.findAll { opt -> if (opt["includeInReproLine"] == false) { return false } diff --git a/gradle/testing/randomization/policies/solr-tests.policy b/gradle/testing/randomization/policies/solr-tests.policy index e5c37b4c912..61df0871a35 100644 --- a/gradle/testing/randomization/policies/solr-tests.policy +++ b/gradle/testing/randomization/policies/solr-tests.policy @@ -50,6 +50,8 @@ grant { permission java.net.SocketPermission "127.0.0.1:4", "connect,resolve"; permission java.net.SocketPermission "127.0.0.1:6", "connect,resolve"; permission java.net.SocketPermission "127.0.0.1:8", "connect,resolve"; + // Used as an invalid ZK host + permission java.net.SocketPermission "----------:33332", "connect,resolve"; // Basic permissions needed for Lucene to work: permission java.util.PropertyPermission "*", "read,write"; @@ -109,6 +111,8 @@ grant { permission java.lang.RuntimePermission "writeFileDescriptor"; // needed by hadoop http permission java.lang.RuntimePermission "getProtectionDomain"; + // SolrProcessMgr to list processes + permission java.lang.RuntimePermission "manageProcess"; // These two *have* to be spelled out a separate permission java.lang.management.ManagementPermission "control"; @@ -250,6 +254,11 @@ grant { // expanded to a wildcard if set, allows all networking everywhere permission java.net.SocketPermission "${solr.internal.network.permission}", "accept,listen,connect,resolve"; + + // Run java + permission java.io.FilePermission "${java.home}${/}-", "execute"; + // Required by SolrProcessManager on Windows to find Solr processes, used by StatusTool (CLI) + permission java.io.FilePermission "<>", "execute"; }; // Grant all permissions to Gradle test runner classes. diff --git a/gradle/testing/slowest-tests-at-end.gradle b/gradle/testing/slowest-tests-at-end.gradle index eaf9cd1a2f1..d24e523394d 100644 --- a/gradle/testing/slowest-tests-at-end.gradle +++ b/gradle/testing/slowest-tests-at-end.gradle @@ -22,7 +22,7 @@ def allSuites = [] allprojects { plugins.withType(JavaPlugin) { - ext { + project.ext { testOptions += [ [propName: 'tests.slowestTests', value: true, description: "Print the summary of the slowest tests."], [propName: 'tests.slowestSuites', value: true, description: "Print the summary of the slowest suites."] diff --git a/gradle/validation/check-environment.gradle b/gradle/validation/check-environment.gradle index 6fcaf761a19..6e5c01ef19c 100644 --- a/gradle/validation/check-environment.gradle +++ b/gradle/validation/check-environment.gradle @@ -22,7 +22,7 @@ import org.gradle.util.GradleVersion configure(rootProject) { ext { - expectedGradleVersion = '8.4' + expectedGradleVersion = '8.10' } wrapper { diff --git a/gradle/validation/ecj-lint/ecj.javadocs.prefs b/gradle/validation/ecj-lint/ecj.javadocs.prefs index 975707055ff..74278547699 100644 --- a/gradle/validation/ecj-lint/ecj.javadocs.prefs +++ b/gradle/validation/ecj-lint/ecj.javadocs.prefs @@ -5,8 +5,8 @@ org.eclipse.jdt.core.compiler.annotation.nonnullbydefault=org.eclipse.jdt.annota org.eclipse.jdt.core.compiler.annotation.nonnullisdefault=disabled org.eclipse.jdt.core.compiler.annotation.nullable=org.eclipse.jdt.annotation.Nullable org.eclipse.jdt.core.compiler.annotation.nullanalysis=disabled -org.eclipse.jdt.core.compiler.codegen.targetPlatform=11 -org.eclipse.jdt.core.compiler.compliance=11 +org.eclipse.jdt.core.compiler.codegen.targetPlatform=17 +org.eclipse.jdt.core.compiler.compliance=17 org.eclipse.jdt.core.compiler.doc.comment.support=enabled org.eclipse.jdt.core.compiler.problem.annotationSuperInterface=error org.eclipse.jdt.core.compiler.problem.assertIdentifier=error @@ -93,4 +93,4 @@ org.eclipse.jdt.core.compiler.problem.unusedParameterWhenOverridingConcrete=disa org.eclipse.jdt.core.compiler.problem.unusedPrivateMember=ignore org.eclipse.jdt.core.compiler.problem.unusedWarningToken=ignore org.eclipse.jdt.core.compiler.problem.varargsArgumentNeedCast=error -org.eclipse.jdt.core.compiler.source=11 +org.eclipse.jdt.core.compiler.source=17 diff --git a/gradle/validation/error-prone.gradle b/gradle/validation/error-prone.gradle index 00e14ed0eab..647ebdeb4fb 100644 --- a/gradle/validation/error-prone.gradle +++ b/gradle/validation/error-prone.gradle @@ -179,6 +179,7 @@ allprojects { prj -> '-Xep:MathRoundIntLong:ERROR', // '-Xep:MislabeledAndroidString:OFF', // we don't use android '-Xep:MisplacedScopeAnnotations:ERROR', + // '-Xep:MissingRuntimeRetention:ERROR', // todo check if useful or comment why not // '-Xep:MissingSuperCall:OFF', // we don't use this annotation // '-Xep:MissingTestCall:OFF', // we don't use this annotation '-Xep:MisusedDayOfYear:ERROR', @@ -218,12 +219,15 @@ allprojects { prj -> '-Xep:RandomCast:ERROR', '-Xep:RandomModInteger:ERROR', // '-Xep:RectIntersectReturnValueIgnored:OFF', // we don't use android + // '-Xep:RedundantSetterCall:ERROR', // todo check if useful or comment why not // '-Xep:RequiredModifiers:OFF', // we don't use this annotation // '-Xep:RestrictedApiChecker:OFF', // we don't use this annotation // '-Xep:ReturnValueIgnored:OFF', // todo there are problems that should be fixed + // '-Xep:SelfAssertion:ERROR', // todo check if useful or comment why not '-Xep:SelfAssignment:ERROR', '-Xep:SelfComparison:ERROR', '-Xep:SelfEquals:ERROR', + // '-Xep:SetUnrecognized:ERROR', // todo check if useful or comment why not // '-Xep:ShouldHaveEvenArgs:OFF', // we don't use truth '-Xep:SizeGreaterThanOrEqualsZero:ERROR', '-Xep:StreamToString:ERROR', @@ -236,7 +240,6 @@ allprojects { prj -> // '-Xep:ThrowIfUncheckedKnownChecked:OFF', // we don't use this annotation '-Xep:ThrowNull:ERROR', '-Xep:TreeToString:ERROR', - // '-Xep:TruthSelfEquals:OFF', // we don't use truth '-Xep:TryFailThrowable:ERROR', '-Xep:TypeParameterQualifier:ERROR', '-Xep:UnicodeDirectionalityCharacters:ERROR', @@ -265,6 +268,7 @@ allprojects { prj -> '-Xep:AssertionFailureIgnored:WARN', '-Xep:AssistedInjectAndInjectOnSameConstructor:WARN', '-Xep:AttemptedNegativeZero:WARN', + // '-Xep:AutoValueBoxedValues:WARN', // todo check if useful or comment why not // '-Xep:AutoValueFinalMethods:OFF', // we don't use autovalue // '-Xep:AutoValueImmutableFields:OFF', // we don't use autovalue // '-Xep:AutoValueSubclassLeaked:OFF', // we don't use autovalue @@ -285,6 +289,7 @@ allprojects { prj -> '-Xep:ChainedAssertionLosesContext:WARN', '-Xep:CharacterGetNumericValue:WARN', '-Xep:ClassCanBeStatic:WARN', + // '-Xep:ClassInitializationDeadlock:WARN', // todo check if useful or comment why not '-Xep:ClassNewInstance:WARN', // '-Xep:CloseableProvides:OFF', // we don't use this annotation '-Xep:ClosingStandardOutputStreams:WARN', @@ -296,6 +301,8 @@ allprojects { prj -> '-Xep:DateChecker:WARN', '-Xep:DateFormatConstant:WARN', // '-Xep:DefaultCharset:OFF', // we have forbiddenapis for that + //'-Xep:DeeplyNested:WARN', // todo check if useful or comment why not + //'-Xep:DefaultLocale:WARN', // todo check if useful or comment why not '-Xep:DefaultPackage:WARN', '-Xep:DeprecatedVariable:WARN', '-Xep:DirectInvocationOnMock:WARN', @@ -309,6 +316,7 @@ allprojects { prj -> '-Xep:EmptyBlockTag:WARN', // '-Xep:EmptyCatch:OFF', // todo check if useful or comment why not - might be handled by ECJ? // '-Xep:EmptySetMultibindingContributions:OFF', // we don't use this annotation + // '-Xep:EnumOrdinal:WARN', // todo check if useful or comment why not '-Xep:EqualsGetClass:WARN', '-Xep:EqualsIncompatibleType:WARN', '-Xep:EqualsUnsafeCast:WARN', @@ -330,6 +338,7 @@ allprojects { prj -> // '-Xep:FragmentNotInstantiable:OFF', // we don't use android // '-Xep:FutureReturnValueIgnored:OFF', // todo there are problems that should be fixed '-Xep:GetClassOnEnum:WARN', + // '-Xep:GuiceNestedCombine:WARN', // todo check if useful or comment why not '-Xep:HidingField:WARN', '-Xep:ICCProfileGetInstance:WARN', '-Xep:IdentityHashMapUsage:WARN', @@ -383,6 +392,7 @@ allprojects { prj -> '-Xep:JodaPlusMinusLong:WARN', '-Xep:JodaTimeConverterManager:WARN', '-Xep:JodaWithDurationAddedLong:WARN', + // '-Xep:JUnitIncompatibleType:WARN', // todo check if useful or comment why not // '-Xep:LabelledBreakTarget:OFF', // stylistic '-Xep:LiteEnumValueOf:WARN', '-Xep:LiteProtoToString:WARN', @@ -403,10 +413,12 @@ allprojects { prj -> // '-Xep:MissingSummary:OFF', // style preference that we don't want to enforce // '-Xep:MixedMutabilityReturnType:OFF', // todo check if useful or comment why not '-Xep:MockNotUsedInProduction:WARN', + // '-Xep:MockitoDoSetup:WARN', // todo check if useful or comment why not '-Xep:ModifiedButNotUsed:WARN', '-Xep:ModifyCollectionInEnhancedForLoop:WARN', '-Xep:ModifySourceCollectionInStream:WARN', '-Xep:MultimapKeys:WARN', + // '-Xep:MultipleNullnessAnnotations:WARN', // todo check if useful or comment why not '-Xep:MultipleParallelOrSequentialCalls:WARN', '-Xep:MultipleUnaryOperatorsInMethodCall:WARN', // '-Xep:MutableGuiceModule:OFF', // we don't use guice @@ -428,7 +440,9 @@ allprojects { prj -> '-Xep:NullableOptional:WARN', // '-Xep:NullablePrimitive:OFF', // we don't use this annotation // '-Xep:NullablePrimitiveArray:OFF', // we don't use this annotation + // '-Xep:NullableTypeParameter:WARN', // todo check if useful or comment why not // '-Xep:NullableVoid:OFF', // we don't use this annotation + // '-Xep:NullableWildcard:WARN', // todo check if useful or comment why not '-Xep:ObjectEqualsForPrimitives:WARN', // '-Xep:ObjectToString:OFF', // todo check if useful or comment why not '-Xep:ObjectsHashCodePrimitive:WARN', @@ -442,6 +456,7 @@ allprojects { prj -> '-Xep:Overrides:WARN', // '-Xep:OverridesGuiceInjectableMethod:OFF', // we don't use guice '-Xep:ParameterName:WARN', + // '-Xep:PatternMatchingInstanceof:WARN', // todo check if useful or comment why not '-Xep:PreconditionsCheckNotNullRepeated:WARN', '-Xep:PrimitiveAtomicReference:WARN', '-Xep:ProtectedMembersInFinalClass:WARN', @@ -459,6 +474,7 @@ allprojects { prj -> // '-Xep:SameNameButDifferent:OFF', // todo check if useful or comment why not '-Xep:SelfAlwaysReturnsThis:WARN', // '-Xep:ShortCircuitBoolean:OFF', // todo check if useful or comment why not + // '-Xep:StatementSwitchToExpressionSwitch:WARN', // todo check if useful or comment why not // '-Xep:StaticAssignmentInConstructor:OFF', // we assign SolrTestCaseJ4.configString in many tests, difficult to untangle '-Xep:StaticAssignmentOfThrowable:WARN', // '-Xep:StaticGuardedByInstance:OFF', // todo check if useful or comment why not @@ -469,9 +485,12 @@ allprojects { prj -> '-Xep:StringCharset:WARN', '-Xep:StringFormatWithLiteral:WARN', // '-Xep:StringSplitter:OFF', // todo check if useful or comment why not - might be able to use forbidden-apis for this? + // '-Xep:SunApi:WARN', // todo check if useful or comment why not + // '-Xep:SuperCallToObjectMethod:WARN', // todo check if useful or comment why not '-Xep:SuperEqualsIsObjectEquals:WARN', // '-Xep:SwigMemoryLeak:OFF', // we don't use swig // '-Xep:SynchronizeOnNonFinalField:OFF', // todo check if useful or comment why not + // '-Xep:SystemConsoleNull:WARN', // todo check if useful or comment why not // '-Xep:ThreadJoinLoop:OFF', // todo check if useful or comment why not // '-Xep:ThreadLocalUsage:OFF', // todo check if useful or comment why not // '-Xep:ThreadPriorityCheck:OFF', // todo check if useful or comment why not @@ -493,6 +512,7 @@ allprojects { prj -> // '-Xep:UnicodeEscape:OFF', // can't enable since Lucene/Solr tests use unicode a bunch // '-Xep:UnnecessaryAssignment:OFF', // we don't use these annotations '-Xep:UnnecessaryAsync:WARN', + // '-Xep:UnnecessaryBreakInSwitch:WARN', // todo check if useful or comment why not '-Xep:UnnecessaryLambda:WARN', '-Xep:UnnecessaryLongToIntConversion:WARN', '-Xep:UnnecessaryMethodInvocationMatcher:WARN', @@ -513,6 +533,7 @@ allprojects { prj -> // '-Xep:UseBinds:OFF', // we don't use this annotation // '-Xep:UseCorrectAssertInTests:OFF', // we inherit from LuceneTestCase which extends Assert '-Xep:VariableNameSameAsType:WARN', + // '-Xep:VoidUsed:WARN', // todo check if useful or comment why not // '-Xep:WaitNotInLoop:OFF', // todo check if useful or comment why not // '-Xep:WakelockReleasedDangerously:OFF', // we don't use android // '-Xep:WithSignatureDiscouraged:OFF', // we aren't using this error-prone internal api diff --git a/gradle/validation/jar-checks.gradle b/gradle/validation/jar-checks.gradle index 6c87c50f023..7547214299d 100644 --- a/gradle/validation/jar-checks.gradle +++ b/gradle/validation/jar-checks.gradle @@ -1,3 +1,5 @@ +import java.util.stream.Collectors + /* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with @@ -74,14 +76,14 @@ subprojects { // Configure jarValidation configuration for all projects. Any dependency // declared on this configuration (or any configuration it extends from) will // be verified. - configurations { + project.configurations { jarValidation } // For Java projects, add all dependencies from the following configurations // to jar validation plugins.withType(JavaPlugin) { - configurations { + project.configurations { jarValidation { extendsFrom runtimeClasspath extendsFrom compileClasspath @@ -107,16 +109,24 @@ subprojects { } def excludeRules = configurations.jarValidation.excludeRules + List> excludeRuleMaps; + if (excludeRules && excludeRules.size() > 0) { + excludeRuleMaps = excludeRules.stream().map {rule -> + if (rule.module != null) { + Map.of("group", rule.group, "module", rule.module) + } else { + Map.of("group", rule.group) + } + }.collect(Collectors.toList()) + } ArrayDeque queue = new ArrayDeque<>() configurations.jarValidation.extendsFrom.each { conf -> - if (excludeRules) { + if (excludeRules && excludeRules.size() > 0) { conf = conf.copyRecursive() conf.canBeResolved = true conf.canBeConsumed = true - def newConfExcludeRules = new HashSet<>(conf.excludeRules) - newConfExcludeRules.addAll(excludeRules) - conf.excludeRules = newConfExcludeRules + excludeRuleMaps.forEach {conf.exclude(it)} } if (conf.canBeResolved) { queue.addAll(conf.resolvedConfiguration.firstLevelModuleDependencies) diff --git a/gradle/validation/spotless.gradle b/gradle/validation/spotless.gradle index 76fecdfad98..d4444a87671 100644 --- a/gradle/validation/spotless.gradle +++ b/gradle/validation/spotless.gradle @@ -24,7 +24,7 @@ configure(allprojects) { prj -> plugins.withType(JavaPlugin) { prj.apply plugin: 'com.diffplug.spotless' - ext { + project.ext { spotlessJavaSetup = (Action){ it.toggleOffOn() // obviously, only to be used sparingly. // TODO: Work out how to support multiple different header files (we have diff --git a/gradle/wrapper/gradle-wrapper.jar.sha256 b/gradle/wrapper/gradle-wrapper.jar.sha256 index f78f56fee75..67dead8f441 100644 --- a/gradle/wrapper/gradle-wrapper.jar.sha256 +++ b/gradle/wrapper/gradle-wrapper.jar.sha256 @@ -1 +1 @@ -0336f591bc0ec9aa0c9988929b93ecc916b3c1d52aed202c7381db144aa0ef15 +2db75c40782f5e8ba1fc278a5574bab070adccb2d21ca5a6e5ed840888448046 diff --git a/gradle/wrapper/gradle-wrapper.jar.version b/gradle/wrapper/gradle-wrapper.jar.version index a2f28f43be3..dd78a707858 100644 --- a/gradle/wrapper/gradle-wrapper.jar.version +++ b/gradle/wrapper/gradle-wrapper.jar.version @@ -1 +1 @@ -8.4.0 +8.10.2 \ No newline at end of file diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties index 744c64d1277..9355b415575 100644 --- a/gradle/wrapper/gradle-wrapper.properties +++ b/gradle/wrapper/gradle-wrapper.properties @@ -1,6 +1,7 @@ distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-8.4-bin.zip +distributionUrl=https\://services.gradle.org/distributions/gradle-8.10-bin.zip networkTimeout=10000 +validateDistributionUrl=true zipStoreBase=GRADLE_USER_HOME zipStorePath=wrapper/dists diff --git a/gradlew b/gradlew index 0aa671a76c2..c8ad2977471 100755 --- a/gradlew +++ b/gradlew @@ -15,6 +15,8 @@ # See the License for the specific language governing permissions and # limitations under the License. # +# SPDX-License-Identifier: Apache-2.0 +# ############################################################################## # @@ -55,7 +57,7 @@ # Darwin, MinGW, and NonStop. # # (3) This script is generated from the Groovy template -# https://github.com/gradle/gradle/blob/HEAD/subprojects/plugins/src/main/resources/org/gradle/api/internal/plugins/unixStartScript.txt +# https://github.com/gradle/gradle/blob/HEAD/platforms/jvm/plugins-application/src/main/resources/org/gradle/api/internal/plugins/unixStartScript.txt # within the Gradle project. # # You can find Gradle at https://github.com/gradle/gradle/. @@ -84,7 +86,8 @@ done # shellcheck disable=SC2034 APP_BASE_NAME=${0##*/} # Discard cd standard output in case $CDPATH is set (https://github.com/gradle/gradle/issues/25036) -APP_HOME=$( cd "${APP_HOME:-./}" > /dev/null && pwd -P ) || exit +APP_HOME=$( cd -P "${APP_HOME:-./}" > /dev/null && printf '%s +' "$PWD" ) || exit # Use the maximum available, or set MAX_FD != -1 to use that value. MAX_FD=maximum @@ -161,7 +164,7 @@ if [ ! -e "$GRADLE_WRAPPER_JAR" ]; then "$JAVACMD" $JAVA_OPTS "$APP_HOME/build-tools/build-infra/src/main/java/org/apache/lucene/gradle/WrapperDownloader.java" "$GRADLE_WRAPPER_JAR" WRAPPER_STATUS=$? if [ "$WRAPPER_STATUS" -eq 1 ]; then - echo "ERROR: Something went wrong. Make sure you're using Java version between 11 and 21." + echo "ERROR: Something went wrong. Make sure you're using Java version between 21 and 23." exit $WRAPPER_STATUS elif [ "$WRAPPER_STATUS" -ne 0 ]; then exit $WRAPPER_STATUS diff --git a/gradlew.bat b/gradlew.bat index 938e3ce94ee..ff65d8f6012 100644 --- a/gradlew.bat +++ b/gradlew.bat @@ -13,6 +13,8 @@ @rem See the License for the specific language governing permissions and @rem limitations under the License. @rem +@rem SPDX-License-Identifier: Apache-2.0 +@rem @if "%DEBUG%"=="" @echo off @rem ########################################################################## @@ -48,11 +50,11 @@ set JAVA_EXE=java.exe %JAVA_EXE% -version >NUL 2>&1 if %ERRORLEVEL% equ 0 goto execute -echo. -echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. -echo. -echo Please set the JAVA_HOME variable in your environment to match the -echo location of your Java installation. +echo. 1>&2 +echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. 1>&2 +echo. 1>&2 +echo Please set the JAVA_HOME variable in your environment to match the 1>&2 +echo location of your Java installation. 1>&2 goto fail @@ -62,11 +64,11 @@ set JAVA_EXE=%JAVA_HOME%/bin/java.exe if exist "%JAVA_EXE%" goto execute -echo. -echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% -echo. -echo Please set the JAVA_HOME variable in your environment to match the -echo location of your Java installation. +echo. 1>&2 +echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% 1>&2 +echo. 1>&2 +echo Please set the JAVA_HOME variable in your environment to match the 1>&2 +echo location of your Java installation. 1>&2 goto fail @@ -108,7 +110,7 @@ goto fail :failWithJvmMessage @rem https://github.com/apache/lucene/pull/819 -echo Error: Something went wrong. Make sure you're using Java version between 11 and 21. +echo Error: Something went wrong. Make sure you're using Java version between 21 and 23. :fail rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of diff --git a/settings.gradle b/settings.gradle index a9dd4a99ba1..7035b75bfdf 100644 --- a/settings.gradle +++ b/settings.gradle @@ -25,7 +25,7 @@ pluginManagement { } plugins { - id 'com.gradle.develocity' version '3.17.6' + id 'com.gradle.develocity' version '3.18.1' id 'com.gradle.common-custom-user-data-gradle-plugin' version '2.0.2' } diff --git a/solr/CHANGES.txt b/solr/CHANGES.txt index 1032406f538..874adfcc4d7 100644 --- a/solr/CHANGES.txt +++ b/solr/CHANGES.txt @@ -10,7 +10,7 @@ New Features --------------------- * SOLR-14496: Solr CLI commands now can interact with a Solr secured using Basic Authentication. (Eric Pugh) -* SOLR-17467: Solr CLI bin/solr start defaults to starting Solr in Cloud mode, use --user-managed switch for User Managed (aka Standalone) mode. (Eric Pugh) +* SOLR-17467: Solr CLI bin/solr start defaults to starting Solr in Cloud mode, use --user-managed switch for User Managed (aka Standalone) mode. (Eric Pugh) Improvements --------------------- @@ -23,6 +23,13 @@ Improvements * SOLR-17077: When a shard rejoins leader election, leave previous election only once to save unneeded calls to Zookeeper. (Pierre Salagnac) +* SOLR-16116: Apache Curator is now used to manage all Solr Zookeeper interactions. This should provide more stability in the Solr-Zookeeper interactions. + The solrj-zookeeper module, now has a dependency on curator. (Houston Putman, Kevin Risden, Mike Drob, David Smiley) + +* SOLR-17544: Solr CLI will now stop when you combine mutually exclusive options. Combining -s and -z options is a common example. (Eric Pugh, Christos Malliaridis) + +* SOLR-17495: Change Solr CLI delete command to not delete configs by default. Decouple lifecycle of collections from configsets. (Eric Pugh) + Optimizations --------------------- (No changes) @@ -73,6 +80,13 @@ Deprecation Removals * SOLR-17400: Remove deprecated script snapshotcli.sh. bin/solr snapshot-* commands have replaced this. (Eric Pugh) +* SOLR-17494: Remove language specific writer types (i.e wt= ruby, python, php, and phps). (Eric Pugh) + +* SOLR-17352: Remove deprecated Solr CLI options. Run bin/solr yourcommand -h to see current options. (Eric Pugh, Christos Malliardis) + +* SOLR-17256: Previously deprecated `SolrRequest` methods `setBasePath` and `getBasePath` have been removed. SolrJ users + wishing to temporarily override an HTTP client's base URL may use `Http2SolrClient.requestWithBaseUrl` instead. (Jason Gerlowski) + Dependency Upgrades --------------------- (No changes) @@ -106,6 +120,8 @@ Other Changes * SOLR-17285: SolrJ RemoteSolrException moved to SolrClient. (@samuelrivascoding) +* SOLR-17321: Minimum Java version for Apache Solr is now 21, and for SolrJ, it is 17. (Sanjay Dutt, David Smiley) + ================== 9.8.0 ================== New Features --------------------- @@ -131,16 +147,22 @@ Improvements which may help reduce distributed-search latency in collections with many shards, especially when PKI is used between nodes. (Jason Gerlowski) -* SOLR-17382: Deprecate -a and -addlopts in favour of --jvm-opts for passing options into the JVM in bin/solr. (Eric Pugh, Christos Malliaridis) - -* SOLR-17431: Deprecate -p parameter where it doesn't refer to a port in bin/solr. (Eric Pugh, Christos Malliaridis) - -* SOLR-17442: Resolve -v flag conflict (version, value, verbose) in bin/solr. (Eric Pugh, Christos Malliaridis) +* SOLR-17383: Resolved overlapping arguments in the Solr CLI. Removed duplicative but differing arguments, + consolidated use of short form arguments -v to not have differing meanings based on tool. Provide deprecation warning + in command line when deprecated arguments are used. (Eric Pugh, Christos Malliaridis) * SOLR-17256: Deprecate SolrRequest `setBasePath` and `getBasePath` methods. SolrJ users wishing to temporarily override an HTTP client's base URL may use `Http2SolrClient.requestWithBaseUrl` instead. (Jason Gerlowski, Sanjay Dutt, David Smiley) +* SOLR-17414: When searching with multiThreaded=true, the internal tasks may now block instead of + enqueuing with a risk of rejection. Solr will use less resources under stress but to get the most + of your machine, you may want to increase the thread pool. (David Smiley) + +* SOLR-17528: Introduce -y short option to bin/solr start --no-prompt option. Aligns with bin/solr package tool. (Eric Pugh) + +* SOLR-17390: EmbeddedSolrServer now considers the ResponseParser (David Smiley) + Optimizations --------------------- * SOLR-14985: Solrj CloudSolrClient with Solr URLs had serious performance regressions (since the @@ -162,6 +184,10 @@ Optimizations * SOLR-17441: Improve system metrics collection by skipping unreadable MXBean properties, making /admin/info/system calls faster (Haythem Khiri) +* SOLR-16503: Switched from HTTP1 to HTTP2 in SolrClientCloudManager by replacing CloudLegacySolrClient with CloudHttp2SolrClient. (Sanjay Dutt, David Smiley) + +* SOLR-17453: Leverage waitForState() instead of busy waiting in CREATE, MIGRATE, REINDEXCOLLECTION, MOVEREPLICA commands, and in some tests. (Pierre Salagnac) + Bug Fixes --------------------- * SOLR-12429: Uploading a configset with a symbolic link produces a IOException. Now a error message to user generated instead. (Eric Pugh) @@ -177,6 +203,13 @@ Bug Fixes * SOLR-17464: Fixed Http2SolrClient bug in that 'requestAsync' triggered NPE when using a shared Jetty client (Jason Gerlowski, James Dyer) +* SOLR-17413: Fixed UpdateLog replay bug that shared thread-unsafe SolrQueryRequest objects across threads (Jason Gerlowski, David Smiley, Houston Putman) + +* SOLR-11191: Splitting shards now routes child-docs with their _root_ field when available so they maintain parent relationship. (Zack Kendall) + +* SOLR-16976: Remove log4j-jul jar and use slf4j bridge for JUL to prevent exception from being logged when remote JMX + is enabled (Shawn Heisey, Stephen Zhou, Eric Pugh, Christine Poerschke, David Smiley) + Dependency Upgrades --------------------- (No changes) @@ -195,6 +228,19 @@ led to the suppression of exceptions. (Andrey Bozhko) * SOLR-11318: Introduce unit testing for AssertTool. (Eric Pugh, Jason Gerlowski) +* SOLR-17534: Introduce ClusterState.getCollectionNames, a convenience method (David Smiley) + +* SOLR-17535: Introduce ClusterState.collectionStream to replace getCollectionStates, getCollectionsMap, + and forEachCollection, which are now deprecated. (David Smiley) + +* SOLR-17545: Upgrade to Gradle 8.10 (Houston Putman) + +================== 9.7.1 ================== +Bug Fixes +--------------------- +* SOLR-17530: Metrics: Thew new Prometheus response writer wasn't detecting TLOG or PULL replicas properly. + (Matthew Biscocho) + ================== 9.7.0 ================== New Features --------------------- diff --git a/solr/api/src/java/org/apache/solr/client/api/endpoint/CreateAliasApi.java b/solr/api/src/java/org/apache/solr/client/api/endpoint/CreateAliasApi.java new file mode 100644 index 00000000000..78b9b4376c0 --- /dev/null +++ b/solr/api/src/java/org/apache/solr/client/api/endpoint/CreateAliasApi.java @@ -0,0 +1,32 @@ +/* + * 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.client.api.endpoint; + +import io.swagger.v3.oas.annotations.Operation; +import jakarta.ws.rs.POST; +import jakarta.ws.rs.Path; +import org.apache.solr.client.api.model.CreateAliasRequestBody; +import org.apache.solr.client.api.model.SolrJerseyResponse; + +@Path("/aliases") +public interface CreateAliasApi { + @POST + @Operation( + summary = "Create a traditional or 'routed' alias", + tags = {"aliases"}) + SolrJerseyResponse createAlias(CreateAliasRequestBody requestBody) throws Exception; +} diff --git a/solr/api/src/java/org/apache/solr/client/api/endpoint/GetSchemaApi.java b/solr/api/src/java/org/apache/solr/client/api/endpoint/GetSchemaApi.java index 8cec1d02f7a..119bf9d19ce 100644 --- a/solr/api/src/java/org/apache/solr/client/api/endpoint/GetSchemaApi.java +++ b/solr/api/src/java/org/apache/solr/client/api/endpoint/GetSchemaApi.java @@ -22,8 +22,16 @@ import jakarta.ws.rs.DefaultValue; import jakarta.ws.rs.GET; import jakarta.ws.rs.Path; +import jakarta.ws.rs.PathParam; import jakarta.ws.rs.QueryParam; +import org.apache.solr.client.api.model.SchemaGetDynamicFieldInfoResponse; +import org.apache.solr.client.api.model.SchemaGetFieldInfoResponse; +import org.apache.solr.client.api.model.SchemaGetFieldTypeInfoResponse; import org.apache.solr.client.api.model.SchemaInfoResponse; +import org.apache.solr.client.api.model.SchemaListCopyFieldsResponse; +import org.apache.solr.client.api.model.SchemaListDynamicFieldsResponse; +import org.apache.solr.client.api.model.SchemaListFieldTypesResponse; +import org.apache.solr.client.api.model.SchemaListFieldsResponse; import org.apache.solr.client.api.model.SchemaNameResponse; import org.apache.solr.client.api.model.SchemaSimilarityResponse; import org.apache.solr.client.api.model.SchemaUniqueKeyResponse; @@ -34,6 +42,67 @@ @Path(INDEX_PATH_PREFIX + "/schema") public interface GetSchemaApi { + @Path(INDEX_PATH_PREFIX + "/schema") + interface Fields { + + @GET + @Path("/fields") + @StoreApiParameters + @Operation( + summary = "List all non-dynamic fields in the schema of the specified core or collection", + tags = {"schema"}) + SchemaListFieldsResponse listSchemaFields(); + + @GET + @Path("/fields/{fieldName}") + @StoreApiParameters + @Operation( + summary = "Get detailed info about a single non-dynamic field", + tags = {"schema"}) + SchemaGetFieldInfoResponse getFieldInfo(@PathParam("fieldName") String fieldName); + + @GET + @Path("/copyfields") + @StoreApiParameters + @Operation( + summary = "List all copy-fields in the schema of the specified core or collection", + tags = {"schema"}) + SchemaListCopyFieldsResponse listCopyFields(); + + @GET + @Path("/dynamicfields") + @StoreApiParameters + @Operation( + summary = "List all dynamic-fields in the schema of the specified core or collection", + tags = {"schema"}) + SchemaListDynamicFieldsResponse listDynamicFields(); + + @GET + @Path("/dynamicfields/{fieldName}") + @StoreApiParameters + @Operation( + summary = "Get detailed info about a single dynamic field", + tags = {"schema"}) + SchemaGetDynamicFieldInfoResponse getDynamicFieldInfo(@PathParam("fieldName") String fieldName); + + @GET + @Path("/fieldtypes") + @StoreApiParameters + @Operation( + summary = "List all field types in the schema used by the specified core or collection", + tags = {"schema"}) + SchemaListFieldTypesResponse listSchemaFieldTypes(); + + @GET + @Path("/fieldtypes/{fieldTypeName}") + @StoreApiParameters + @Operation( + summary = "Get detailed info about a single field type", + tags = {"schema"}) + SchemaGetFieldTypeInfoResponse getFieldTypeInfo( + @PathParam("fieldTypeName") String fieldTypeName); + } + @GET @StoreApiParameters @Operation( diff --git a/solr/api/src/java/org/apache/solr/client/api/endpoint/NodeLoggingApis.java b/solr/api/src/java/org/apache/solr/client/api/endpoint/NodeLoggingApis.java new file mode 100644 index 00000000000..c5b5cd95807 --- /dev/null +++ b/solr/api/src/java/org/apache/solr/client/api/endpoint/NodeLoggingApis.java @@ -0,0 +1,61 @@ +/* + * 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.client.api.endpoint; + +import io.swagger.v3.oas.annotations.Operation; +import jakarta.ws.rs.GET; +import jakarta.ws.rs.PUT; +import jakarta.ws.rs.Path; +import jakarta.ws.rs.QueryParam; +import java.util.List; +import org.apache.solr.client.api.model.ListLevelsResponse; +import org.apache.solr.client.api.model.LogLevelChange; +import org.apache.solr.client.api.model.LogMessagesResponse; +import org.apache.solr.client.api.model.LoggingResponse; +import org.apache.solr.client.api.model.SetThresholdRequestBody; + +@Path("/node/logging") +public interface NodeLoggingApis { + + @GET + @Path("/levels") + @Operation( + summary = "List all log-levels for the target node.", + tags = {"logging"}) + ListLevelsResponse listAllLoggersAndLevels(); + + @PUT + @Path("/levels") + @Operation( + summary = "Set one or more logger levels on the target node.", + tags = {"logging"}) + LoggingResponse modifyLocalLogLevel(List requestBody); + + @GET + @Path("/messages") + @Operation( + summary = "Fetch recent log messages on the targeted node.", + tags = {"logging"}) + LogMessagesResponse fetchLocalLogMessages(@QueryParam("since") Long boundingTimeMillis); + + @PUT + @Path("/messages/threshold") + @Operation( + summary = "Set a threshold level for the targeted node's log message watcher.", + tags = {"logging"}) + LoggingResponse setMessageThreshold(SetThresholdRequestBody requestBody); +} diff --git a/solr/api/src/java/org/apache/solr/client/api/endpoint/ReplicationApis.java b/solr/api/src/java/org/apache/solr/client/api/endpoint/ReplicationApis.java new file mode 100644 index 00000000000..ac33894b656 --- /dev/null +++ b/solr/api/src/java/org/apache/solr/client/api/endpoint/ReplicationApis.java @@ -0,0 +1,50 @@ +/* + * 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.client.api.endpoint; + +import io.swagger.v3.oas.annotations.Operation; +import io.swagger.v3.oas.annotations.Parameter; +import jakarta.ws.rs.GET; +import jakarta.ws.rs.Path; +import jakarta.ws.rs.QueryParam; +import java.io.IOException; +import org.apache.solr.client.api.model.FileListResponse; +import org.apache.solr.client.api.model.IndexVersionResponse; +import org.apache.solr.client.api.util.CoreApiParameters; + +@Path("/cores/{coreName}/replication") +public interface ReplicationApis { + + @GET + @CoreApiParameters + @Path("/indexversion") + @Operation( + summary = "Return the index version of the specified core.", + tags = {"replication"}) + IndexVersionResponse fetchIndexVersion() throws IOException; + + @GET + @CoreApiParameters + @Path("/files") + @Operation( + summary = "Return the list of index file that make up the specified core.", + tags = {"replication"}) + FileListResponse fetchFileList( + @Parameter(description = "The generation number of the index", required = true) + @QueryParam("generation") + long gen); +} diff --git a/solr/api/src/java/org/apache/solr/client/api/model/CategoryRoutedAliasProperties.java b/solr/api/src/java/org/apache/solr/client/api/model/CategoryRoutedAliasProperties.java new file mode 100644 index 00000000000..c3882e0b8a3 --- /dev/null +++ b/solr/api/src/java/org/apache/solr/client/api/model/CategoryRoutedAliasProperties.java @@ -0,0 +1,27 @@ +/* + * 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.client.api.model; + +import com.fasterxml.jackson.annotation.JsonProperty; + +public class CategoryRoutedAliasProperties extends RoutedAliasProperties { + @JsonProperty("maxCardinality") + public Long maxCardinality; + + @JsonProperty("mustMatch") + public String mustMatch; +} diff --git a/solr/api/src/java/org/apache/solr/client/api/model/CreateAliasRequestBody.java b/solr/api/src/java/org/apache/solr/client/api/model/CreateAliasRequestBody.java new file mode 100644 index 00000000000..f4fee3a2d39 --- /dev/null +++ b/solr/api/src/java/org/apache/solr/client/api/model/CreateAliasRequestBody.java @@ -0,0 +1,42 @@ +/* + * 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.client.api.model; + +import com.fasterxml.jackson.annotation.JsonProperty; +import io.swagger.v3.oas.annotations.media.Schema; +import java.util.List; + +public class CreateAliasRequestBody { + @JsonProperty(required = true) + public String name; + + @JsonProperty("collections") + public List collections; + + @JsonProperty("async") + public String async; + + @JsonProperty("routers") + public List routers; + + @Schema( + description = + "Parameters to be used for any collections created by this alias. Only used for 'routed' aliases", + name = "collCreationParameters") + @JsonProperty("create-collection") + public CreateCollectionRequestBody collCreationParameters; +} diff --git a/solr/api/src/java/org/apache/solr/client/api/model/FileListResponse.java b/solr/api/src/java/org/apache/solr/client/api/model/FileListResponse.java new file mode 100644 index 00000000000..d42260449a4 --- /dev/null +++ b/solr/api/src/java/org/apache/solr/client/api/model/FileListResponse.java @@ -0,0 +1,38 @@ +/* + * 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.client.api.model; + +import com.fasterxml.jackson.annotation.JsonProperty; +import java.util.List; + +/** Response body for the `GET /api/cores/coreName/replication/files` API */ +public class FileListResponse extends SolrJerseyResponse { + @JsonProperty("filelist") + public List fileList; + + @JsonProperty("confFiles") + public List confFiles; + + @JsonProperty("status") + public String status; + + @JsonProperty("message") + public String message; + + @JsonProperty("exception") + public Exception exception; +} diff --git a/solr/api/src/java/org/apache/solr/client/api/model/FileMetaData.java b/solr/api/src/java/org/apache/solr/client/api/model/FileMetaData.java new file mode 100644 index 00000000000..79f4d659021 --- /dev/null +++ b/solr/api/src/java/org/apache/solr/client/api/model/FileMetaData.java @@ -0,0 +1,42 @@ +/* + * 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.client.api.model; + +import com.fasterxml.jackson.annotation.JsonProperty; + +public class FileMetaData { + + @JsonProperty("size") + public long size; + + @JsonProperty("name") + public String name; + + @JsonProperty("checksum") + public long checksum; + + @JsonProperty("alias") + public String alias; + + public FileMetaData() {} + + public FileMetaData(long size, String name, long checksum) { + this.size = size; + this.name = name; + this.checksum = checksum; + } +} diff --git a/solr/api/src/java/org/apache/solr/client/api/model/IndexVersionResponse.java b/solr/api/src/java/org/apache/solr/client/api/model/IndexVersionResponse.java new file mode 100644 index 00000000000..0d5633ca6e8 --- /dev/null +++ b/solr/api/src/java/org/apache/solr/client/api/model/IndexVersionResponse.java @@ -0,0 +1,40 @@ +/* + * 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.client.api.model; + +import com.fasterxml.jackson.annotation.JsonProperty; + +/** Response body for the `GET /api/cores/coreName/replication/indexversion` API */ +public class IndexVersionResponse extends SolrJerseyResponse { + + @JsonProperty("indexversion") + public Long indexVersion; + + @JsonProperty("generation") + public Long generation; + + @JsonProperty("status") + public String status; + + public IndexVersionResponse() {} + + public IndexVersionResponse(Long indexVersion, Long generation, String status) { + this.indexVersion = indexVersion; + this.generation = generation; + this.status = status; + } +} diff --git a/solr/api/src/java/org/apache/solr/client/api/model/ListLevelsResponse.java b/solr/api/src/java/org/apache/solr/client/api/model/ListLevelsResponse.java new file mode 100644 index 00000000000..b7ad63ac4c1 --- /dev/null +++ b/solr/api/src/java/org/apache/solr/client/api/model/ListLevelsResponse.java @@ -0,0 +1,26 @@ +/* + * 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.client.api.model; + +import com.fasterxml.jackson.annotation.JsonProperty; +import java.util.List; + +/** Response format for the 'GET /api/node/logging/levels' API. */ +public class ListLevelsResponse extends LoggingResponse { + @JsonProperty public List levels; + @JsonProperty public List loggers; +} diff --git a/solr/core/src/java/org/apache/solr/servlet/BaseSolrServlet.java b/solr/api/src/java/org/apache/solr/client/api/model/LogLevelChange.java similarity index 65% rename from solr/core/src/java/org/apache/solr/servlet/BaseSolrServlet.java rename to solr/api/src/java/org/apache/solr/client/api/model/LogLevelChange.java index 85aca08cd86..31443a5dc8d 100644 --- a/solr/core/src/java/org/apache/solr/servlet/BaseSolrServlet.java +++ b/solr/api/src/java/org/apache/solr/client/api/model/LogLevelChange.java @@ -14,19 +14,19 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package org.apache.solr.servlet; +package org.apache.solr.client.api.model; -import javax.servlet.http.HttpServlet; +import com.fasterxml.jackson.annotation.JsonProperty; -/** - * All Solr servlets available to the user's webapp should extend this class and not {@link - * HttpServlet}. This class ensures that the logging configuration is correct before any Solr - * specific code is executed. - */ -@SuppressWarnings("serial") -abstract class BaseSolrServlet extends HttpServlet { +/** A user-requested modification in the level that a specified logger reports at. */ +public class LogLevelChange { + public LogLevelChange() {} - static { - CheckLoggingConfiguration.check(); + public LogLevelChange(String logger, String level) { + this.logger = logger; + this.level = level; } + + @JsonProperty public String logger; + @JsonProperty public String level; } diff --git a/solr/api/src/java/org/apache/solr/client/api/model/LogLevelInfo.java b/solr/api/src/java/org/apache/solr/client/api/model/LogLevelInfo.java new file mode 100644 index 00000000000..9bde4b1657a --- /dev/null +++ b/solr/api/src/java/org/apache/solr/client/api/model/LogLevelInfo.java @@ -0,0 +1,39 @@ +/* + * 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.client.api.model; + +import com.fasterxml.jackson.annotation.JsonProperty; + +/** Representation of a single logger and its current state. */ +public class LogLevelInfo { + public LogLevelInfo() {} + + public LogLevelInfo(String name, String level, boolean set) { + this.name = name; + this.level = level; + this.set = set; + } + + @JsonProperty("name") + public String name; + + @JsonProperty("level") + public String level; + + @JsonProperty("set") + public boolean set; +} diff --git a/solr/api/src/java/org/apache/solr/client/api/model/LogMessageInfo.java b/solr/api/src/java/org/apache/solr/client/api/model/LogMessageInfo.java new file mode 100644 index 00000000000..7596cc28f68 --- /dev/null +++ b/solr/api/src/java/org/apache/solr/client/api/model/LogMessageInfo.java @@ -0,0 +1,35 @@ +/* + * 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.client.api.model; + +import com.fasterxml.jackson.annotation.JsonProperty; +import java.util.List; + +/** Metadata about the log messages returned by the 'GET /api/node/logging/messages' API */ +public class LogMessageInfo { + @JsonProperty("since") + public Long boundingTimeMillis; + + @JsonProperty public Boolean found; + @JsonProperty public List levels; + + @JsonProperty("last") + public long lastRecordTimestampMillis; + + @JsonProperty public int buffer; + @JsonProperty public String threshold; +} diff --git a/solr/api/src/java/org/apache/solr/client/api/model/LogMessagesResponse.java b/solr/api/src/java/org/apache/solr/client/api/model/LogMessagesResponse.java new file mode 100644 index 00000000000..fb979afdfeb --- /dev/null +++ b/solr/api/src/java/org/apache/solr/client/api/model/LogMessagesResponse.java @@ -0,0 +1,29 @@ +/* + * 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.client.api.model; + +import com.fasterxml.jackson.annotation.JsonProperty; + +/** Response format for the 'GET /api/node/logging/messages' API. */ +public class LogMessagesResponse extends LoggingResponse { + @JsonProperty public LogMessageInfo info; + + // TODO Make this declaration more specific. Value on the server side is currently a + // SolrDocumentList, which cannot live in 'api' + @JsonProperty("history") + public Object docs; +} diff --git a/solr/api/src/java/org/apache/solr/client/api/model/LoggingResponse.java b/solr/api/src/java/org/apache/solr/client/api/model/LoggingResponse.java new file mode 100644 index 00000000000..1ba4be2c0d3 --- /dev/null +++ b/solr/api/src/java/org/apache/solr/client/api/model/LoggingResponse.java @@ -0,0 +1,25 @@ +/* + * 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.client.api.model; + +import com.fasterxml.jackson.annotation.JsonProperty; + +/** Generic logging response that includes the name of the log watcher (e.g. "Log4j2") */ +public class LoggingResponse extends SolrJerseyResponse { + @JsonProperty("watcher") + public String watcherName; +} diff --git a/solr/api/src/java/org/apache/solr/client/api/model/RoutedAliasProperties.java b/solr/api/src/java/org/apache/solr/client/api/model/RoutedAliasProperties.java new file mode 100644 index 00000000000..8355937e70b --- /dev/null +++ b/solr/api/src/java/org/apache/solr/client/api/model/RoutedAliasProperties.java @@ -0,0 +1,31 @@ +/* + * 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.client.api.model; + +import com.fasterxml.jackson.annotation.JsonProperty; +import com.fasterxml.jackson.annotation.JsonSubTypes; +import com.fasterxml.jackson.annotation.JsonTypeInfo; + +@JsonTypeInfo(use = JsonTypeInfo.Id.NAME, include = JsonTypeInfo.As.PROPERTY, property = "type") +@JsonSubTypes({ + @JsonSubTypes.Type(value = TimeRoutedAliasProperties.class, name = "time"), + @JsonSubTypes.Type(value = CategoryRoutedAliasProperties.class, name = "category") +}) +public abstract class RoutedAliasProperties { + @JsonProperty(required = true) + public String field; +} diff --git a/solr/api/src/java/org/apache/solr/client/api/model/SchemaGetDynamicFieldInfoResponse.java b/solr/api/src/java/org/apache/solr/client/api/model/SchemaGetDynamicFieldInfoResponse.java new file mode 100644 index 00000000000..626828c42cd --- /dev/null +++ b/solr/api/src/java/org/apache/solr/client/api/model/SchemaGetDynamicFieldInfoResponse.java @@ -0,0 +1,27 @@ +/* + * 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.client.api.model; + +import com.fasterxml.jackson.annotation.JsonProperty; + +public class SchemaGetDynamicFieldInfoResponse extends SolrJerseyResponse { + + // TODO Server code sets this field as 'SimpleOrderedMap'; make this type declaration more + // specific once SOLR-12959 is completed + @JsonProperty("dynamicField") + public Object dynamicFieldInfo; +} diff --git a/solr/api/src/java/org/apache/solr/client/api/model/SchemaGetFieldInfoResponse.java b/solr/api/src/java/org/apache/solr/client/api/model/SchemaGetFieldInfoResponse.java new file mode 100644 index 00000000000..9b94dbda428 --- /dev/null +++ b/solr/api/src/java/org/apache/solr/client/api/model/SchemaGetFieldInfoResponse.java @@ -0,0 +1,27 @@ +/* + * 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.client.api.model; + +import com.fasterxml.jackson.annotation.JsonProperty; + +public class SchemaGetFieldInfoResponse extends SolrJerseyResponse { + + // TODO Server code sets this field as 'SimpleOrderedMap'; make this type declaration more + // specific once SOLR-12959 is completed + @JsonProperty("field") + public Object fieldInfo; +} diff --git a/solr/api/src/java/org/apache/solr/client/api/model/SchemaGetFieldTypeInfoResponse.java b/solr/api/src/java/org/apache/solr/client/api/model/SchemaGetFieldTypeInfoResponse.java new file mode 100644 index 00000000000..8e243cc111c --- /dev/null +++ b/solr/api/src/java/org/apache/solr/client/api/model/SchemaGetFieldTypeInfoResponse.java @@ -0,0 +1,27 @@ +/* + * 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.client.api.model; + +import com.fasterxml.jackson.annotation.JsonProperty; + +public class SchemaGetFieldTypeInfoResponse extends SolrJerseyResponse { + + // TODO Server code sets this field as 'SimpleOrderedMap'; make this type declaration more + // specific once SOLR-12959 is completed + @JsonProperty("fieldType") + public Object fieldTypeInfo; +} diff --git a/solr/api/src/java/org/apache/solr/client/api/model/SchemaListCopyFieldsResponse.java b/solr/api/src/java/org/apache/solr/client/api/model/SchemaListCopyFieldsResponse.java new file mode 100644 index 00000000000..ca18e9fa711 --- /dev/null +++ b/solr/api/src/java/org/apache/solr/client/api/model/SchemaListCopyFieldsResponse.java @@ -0,0 +1,25 @@ +/* + * 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.client.api.model; + +import com.fasterxml.jackson.annotation.JsonProperty; +import java.util.List; + +public class SchemaListCopyFieldsResponse extends SolrJerseyResponse { + @JsonProperty("copyFields") + public List copyFields; +} diff --git a/solr/api/src/java/org/apache/solr/client/api/model/SchemaListDynamicFieldsResponse.java b/solr/api/src/java/org/apache/solr/client/api/model/SchemaListDynamicFieldsResponse.java new file mode 100644 index 00000000000..7c43baf6020 --- /dev/null +++ b/solr/api/src/java/org/apache/solr/client/api/model/SchemaListDynamicFieldsResponse.java @@ -0,0 +1,25 @@ +/* + * 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.client.api.model; + +import com.fasterxml.jackson.annotation.JsonProperty; +import java.util.List; + +public class SchemaListDynamicFieldsResponse extends SolrJerseyResponse { + @JsonProperty("dynamicFields") + public List dynamicFields; +} diff --git a/solr/api/src/java/org/apache/solr/client/api/model/SchemaListFieldTypesResponse.java b/solr/api/src/java/org/apache/solr/client/api/model/SchemaListFieldTypesResponse.java new file mode 100644 index 00000000000..1b8033352a5 --- /dev/null +++ b/solr/api/src/java/org/apache/solr/client/api/model/SchemaListFieldTypesResponse.java @@ -0,0 +1,25 @@ +/* + * 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.client.api.model; + +import com.fasterxml.jackson.annotation.JsonProperty; +import java.util.List; + +public class SchemaListFieldTypesResponse extends SolrJerseyResponse { + @JsonProperty("fieldTypes") + public List fieldTypes; +} diff --git a/solr/solrj-zookeeper/src/java/org/apache/solr/common/cloud/BeforeReconnect.java b/solr/api/src/java/org/apache/solr/client/api/model/SchemaListFieldsResponse.java similarity index 76% rename from solr/solrj-zookeeper/src/java/org/apache/solr/common/cloud/BeforeReconnect.java rename to solr/api/src/java/org/apache/solr/client/api/model/SchemaListFieldsResponse.java index 928e606c920..4ab6f737c2d 100644 --- a/solr/solrj-zookeeper/src/java/org/apache/solr/common/cloud/BeforeReconnect.java +++ b/solr/api/src/java/org/apache/solr/client/api/model/SchemaListFieldsResponse.java @@ -14,8 +14,12 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package org.apache.solr.common.cloud; +package org.apache.solr.client.api.model; -public interface BeforeReconnect { - public void command(); +import com.fasterxml.jackson.annotation.JsonProperty; +import java.util.List; + +public class SchemaListFieldsResponse extends SolrJerseyResponse { + @JsonProperty("fields") + public List fields; } diff --git a/solr/core/src/java/org/apache/solr/servlet/BaseSolrFilter.java b/solr/api/src/java/org/apache/solr/client/api/model/SetThresholdRequestBody.java similarity index 67% rename from solr/core/src/java/org/apache/solr/servlet/BaseSolrFilter.java rename to solr/api/src/java/org/apache/solr/client/api/model/SetThresholdRequestBody.java index d16d722447d..3dd5b070798 100644 --- a/solr/core/src/java/org/apache/solr/servlet/BaseSolrFilter.java +++ b/solr/api/src/java/org/apache/solr/client/api/model/SetThresholdRequestBody.java @@ -14,18 +14,18 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package org.apache.solr.servlet; +package org.apache.solr.client.api.model; -import javax.servlet.Filter; +import com.fasterxml.jackson.annotation.JsonProperty; -/** - * All Solr filters available to the user's webapp should extend this class and not just implement - * {@link Filter}. This class ensures that the logging configuration is correct before any Solr - * specific code is executed. - */ -abstract class BaseSolrFilter implements Filter { +/** The request body for the 'PUT /api/node/logging/messages/threshold' API. */ +public class SetThresholdRequestBody { + public SetThresholdRequestBody() {} - static { - CheckLoggingConfiguration.check(); + public SetThresholdRequestBody(String level) { + this.level = level; } + + @JsonProperty(required = true) + public String level; } diff --git a/solr/api/src/java/org/apache/solr/client/api/model/TimeRoutedAliasProperties.java b/solr/api/src/java/org/apache/solr/client/api/model/TimeRoutedAliasProperties.java new file mode 100644 index 00000000000..8a953cfaf94 --- /dev/null +++ b/solr/api/src/java/org/apache/solr/client/api/model/TimeRoutedAliasProperties.java @@ -0,0 +1,41 @@ +/* + * 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.client.api.model; + +import com.fasterxml.jackson.annotation.JsonProperty; + +public class TimeRoutedAliasProperties extends RoutedAliasProperties { + // Expected to be a date/time in ISO format, or 'NOW' + @JsonProperty(required = true) + public String start; + + // TODO Change this to 'timezone' or something less abbreviated + @JsonProperty("tz") + public String tz; + + @JsonProperty(required = true) + public String interval; + + @JsonProperty("maxFutureMs") + public Long maxFutureMs; + + @JsonProperty("preemptiveCreateMath") + public String preemptiveCreateMath; + + @JsonProperty("autoDeleteAge") + public String autoDeleteAge; +} diff --git a/solr/api/src/java/org/apache/solr/client/api/util/Constants.java b/solr/api/src/java/org/apache/solr/client/api/util/Constants.java index b4ef56c2050..49e69d37fac 100644 --- a/solr/api/src/java/org/apache/solr/client/api/util/Constants.java +++ b/solr/api/src/java/org/apache/solr/client/api/util/Constants.java @@ -27,6 +27,8 @@ private Constants() { public static final String INDEX_PATH_PREFIX = "/{" + INDEX_TYPE_PATH_PARAMETER + ":cores|collections}/{" + INDEX_NAME_PATH_PARAMETER + "}"; + public static final String CORE_NAME_PATH_PARAMETER = "coreName"; + public static final String OMIT_FROM_CODEGEN_PROPERTY = "omitFromCodegen"; public static final String GENERIC_ENTITY_PROPERTY = "genericEntity"; diff --git a/solr/api/src/java/org/apache/solr/client/api/util/CoreApiParameters.java b/solr/api/src/java/org/apache/solr/client/api/util/CoreApiParameters.java new file mode 100644 index 00000000000..7151ee9eda7 --- /dev/null +++ b/solr/api/src/java/org/apache/solr/client/api/util/CoreApiParameters.java @@ -0,0 +1,40 @@ +/* + * 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.client.api.util; + +import static org.apache.solr.client.api.util.Constants.CORE_NAME_PATH_PARAMETER; + +import io.swagger.v3.oas.annotations.Parameter; +import io.swagger.v3.oas.annotations.enums.ParameterIn; +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; + +/** + * Concisely collects the parameters shared by APIs that interact with contents of a specific core. + * + *

Not to be used on APIs that apply to both cores AND collections. {@link StoreApiParameters} + * should be used in those cases. + * + *

Used primarily as a way to avoid duplicating these parameter definitions on each relevant + * interface method in {@link org.apache.solr.client.api.endpoint} + */ +@Target({ElementType.METHOD, ElementType.TYPE, ElementType.PARAMETER, ElementType.FIELD}) +@Retention(RetentionPolicy.RUNTIME) +@Parameter(name = CORE_NAME_PATH_PARAMETER, in = ParameterIn.PATH) +public @interface CoreApiParameters {} diff --git a/solr/api/src/java/org/apache/solr/client/api/util/StoreApiParameters.java b/solr/api/src/java/org/apache/solr/client/api/util/StoreApiParameters.java index b82f4cd107a..1d9a66bfa9c 100644 --- a/solr/api/src/java/org/apache/solr/client/api/util/StoreApiParameters.java +++ b/solr/api/src/java/org/apache/solr/client/api/util/StoreApiParameters.java @@ -29,8 +29,10 @@ import org.apache.solr.client.api.model.IndexType; /** - * Concisely collects the parameters shared by APIs that interact with contents of a specific - * core/collection. + * Concisely collects the parameters shared by APIs that interact with contents of a specific core + * OR collection. + * + *

Not to be used on APIs that are only available on cores or only on collections. * *

Used primarily as a way to avoid duplicating these parameter definitions on each relevant * interface method in {@link org.apache.solr.client.api.endpoint} diff --git a/solr/benchmark/jmh.sh b/solr/benchmark/jmh.sh index 30c72b7a2e7..18f9875da19 100755 --- a/solr/benchmark/jmh.sh +++ b/solr/benchmark/jmh.sh @@ -51,9 +51,7 @@ echo "running JMH with args: $@" # -XX:+UnlockExperimentalVMOptions -XX:G1NewSizePercent=20 # and this note: Prevents G1 undermining young gen, which otherwise causes a cascade of issues # MRM: I've also seen 15 claimed as a sweet spot. -# -XX:-UseBiasedLocking - should be unreflective in recent JVMs and removed in the latest. - -jvmArgs="-jvmArgs -Djmh.shutdownTimeout=5 -jvmArgs -Djmh.shutdownTimeout.step=3 -jvmArgs -Djava.security.egd=file:/dev/./urandom -jvmArgs -XX:-UseBiasedLocking -jvmArgs -XX:+UnlockDiagnosticVMOptions -jvmArgs -XX:+DebugNonSafepoints -jvmArgs --add-opens=java.base/java.lang.reflect=ALL-UNNAMED" +jvmArgs="-jvmArgs -Djmh.shutdownTimeout=5 -jvmArgs -Djmh.shutdownTimeout.step=3 -jvmArgs -Djava.security.egd=file:/dev/./urandom -jvmArgs -XX:+UnlockDiagnosticVMOptions -jvmArgs -XX:+DebugNonSafepoints -jvmArgs --add-opens=java.base/java.lang.reflect=ALL-UNNAMED" gcArgs="-jvmArgs -XX:+UseG1GC -jvmArgs -XX:+ParallelRefProcEnabled" # -jvmArgs -Dlog4j2.debug diff --git a/solr/benchmark/src/java/org/apache/solr/bench/MiniClusterState.java b/solr/benchmark/src/java/org/apache/solr/bench/MiniClusterState.java index 88bfc05af1f..34a970b3392 100755 --- a/solr/benchmark/src/java/org/apache/solr/bench/MiniClusterState.java +++ b/solr/benchmark/src/java/org/apache/solr/bench/MiniClusterState.java @@ -37,7 +37,6 @@ import java.util.concurrent.Executors; import java.util.concurrent.ScheduledExecutorService; import java.util.concurrent.TimeUnit; -import org.apache.solr.client.solrj.SolrClient; import org.apache.solr.client.solrj.SolrQuery; import org.apache.solr.client.solrj.SolrServerException; import org.apache.solr.client.solrj.impl.Http2SolrClient; @@ -84,7 +83,7 @@ public static class MiniClusterBenchState { MiniSolrCloudCluster cluster; /** The Client. */ - public SolrClient client; + public Http2SolrClient client; /** The Run cnt. */ int runCnt = 0; @@ -288,7 +287,7 @@ public void startMiniCluster(int nodeCount) { } zkHost = cluster.getZkServer().getZkAddress(); - client = new Http2SolrClient.Builder().useHttp1_1(useHttp1).build(); + client = new Http2SolrClient.Builder(nodes.get(0)).useHttp1_1(useHttp1).build(); log("done starting mini cluster"); log(""); @@ -318,9 +317,8 @@ public void createCollection(String collection, int numShards, int numReplicas) CollectionAdminRequest.Create request = CollectionAdminRequest.createCollection(collection, "conf", numShards, numReplicas); - request.setBasePath(nodes.get(random.nextInt(cluster.getJettySolrRunners().size()))); - - client.request(request); + client.requestWithBaseUrl( + nodes.get(random.nextInt(cluster.getJettySolrRunners().size())), null, request); cluster.waitForActiveCollection( collection, 15, TimeUnit.SECONDS, numShards, numShards * numReplicas); @@ -368,18 +366,19 @@ public void index(String collection, Docs docs, int docCount, boolean parallel) log("committing data ..."); UpdateRequest commitRequest = new UpdateRequest(); - commitRequest.setBasePath(nodes.get(random.nextInt(cluster.getJettySolrRunners().size()))); + final var url = nodes.get(random.nextInt(cluster.getJettySolrRunners().size())); commitRequest.setAction(UpdateRequest.ACTION.COMMIT, false, true); - commitRequest.process(client, collection); + client.requestWithBaseUrl(url, collection, commitRequest); log("done committing data"); } else { cluster.waitForActiveCollection(collection, 15, TimeUnit.SECONDS); } QueryRequest queryRequest = new QueryRequest(new SolrQuery("q", "*:*", "rows", "1")); - queryRequest.setBasePath(nodes.get(random.nextInt(cluster.getJettySolrRunners().size()))); + final var url = nodes.get(random.nextInt(cluster.getJettySolrRunners().size())); + NamedList result = + client.requestWithBaseUrl(url, collection, queryRequest).getResponse(); - NamedList result = client.request(queryRequest, collection); log("sanity check of single row query result: " + result); log(""); @@ -417,15 +416,15 @@ private void indexParallel(String collection, Docs docs, int docCount) @Override public void run() { UpdateRequest updateRequest = new UpdateRequest(); - updateRequest.setBasePath( - nodes.get(threadRandom.nextInt(cluster.getJettySolrRunners().size()))); + final var url = + nodes.get(threadRandom.nextInt(cluster.getJettySolrRunners().size())); SolrInputDocument doc = docs.inputDocument(); // log("add doc " + doc); updateRequest.add(doc); meter.mark(); try { - client.request(updateRequest, collection); + client.requestWithBaseUrl(url, collection, updateRequest); } catch (Exception e) { throw new RuntimeException(e); } @@ -452,9 +451,8 @@ private void indexBatch(String collection, Docs docs, int docCount, int batchSiz batch.add(docs.inputDocument()); if (i % batchSize == 0) { UpdateRequest updateRequest = new UpdateRequest(); - updateRequest.setBasePath(nodes.get(0)); updateRequest.add(batch); - client.request(updateRequest, collection); + client.requestWithBaseUrl(nodes.get(0), collection, updateRequest); meter.mark(batch.size()); batch.clear(); log(meter.getCount() + " docs at " + (long) meter.getMeanRate() + " doc/s"); @@ -462,9 +460,8 @@ private void indexBatch(String collection, Docs docs, int docCount, int batchSiz } if (!batch.isEmpty()) { UpdateRequest updateRequest = new UpdateRequest(); - updateRequest.setBasePath(nodes.get(0)); updateRequest.add(batch); - client.request(updateRequest, collection); + client.requestWithBaseUrl(nodes.get(0), collection, updateRequest); meter.mark(batch.size()); batch = null; } @@ -500,10 +497,9 @@ public void forceMerge(String collection, int maxMergeSegments) throws Exception } UpdateRequest optimizeRequest = new UpdateRequest(); - optimizeRequest.setBasePath( - nodes.get(random.nextInt(cluster.getJettySolrRunners().size()))); + final var url = nodes.get(random.nextInt(cluster.getJettySolrRunners().size())); optimizeRequest.setAction(UpdateRequest.ACTION.OPTIMIZE, false, true, maxMergeSegments); - optimizeRequest.process(client, collection); + client.requestWithBaseUrl(url, collection, optimizeRequest); } } diff --git a/solr/benchmark/src/java/org/apache/solr/bench/index/CloudIndexing.java b/solr/benchmark/src/java/org/apache/solr/bench/index/CloudIndexing.java index 820f2130a60..0ee950e7231 100755 --- a/solr/benchmark/src/java/org/apache/solr/bench/index/CloudIndexing.java +++ b/solr/benchmark/src/java/org/apache/solr/bench/index/CloudIndexing.java @@ -127,9 +127,9 @@ public void doSetup(MiniClusterState.MiniClusterBenchState miniClusterState) thr public Object indexDoc(MiniClusterState.MiniClusterBenchState miniClusterState, BenchState state) throws Exception { UpdateRequest updateRequest = new UpdateRequest(); - updateRequest.setBasePath( - miniClusterState.nodes.get(miniClusterState.getRandom().nextInt(state.nodeCount))); updateRequest.add(state.getNextDoc()); - return miniClusterState.client.request(updateRequest, BenchState.COLLECTION); + final var url = + miniClusterState.nodes.get(miniClusterState.getRandom().nextInt(state.nodeCount)); + return miniClusterState.client.requestWithBaseUrl(url, BenchState.COLLECTION, updateRequest); } } diff --git a/solr/benchmark/src/java/org/apache/solr/bench/search/FilterCache.java b/solr/benchmark/src/java/org/apache/solr/bench/search/FilterCache.java index e518ff90865..6b7f6bf4a4f 100644 --- a/solr/benchmark/src/java/org/apache/solr/bench/search/FilterCache.java +++ b/solr/benchmark/src/java/org/apache/solr/bench/search/FilterCache.java @@ -68,6 +68,7 @@ public static class BenchState { QueryRequest q1 = new QueryRequest(new SolrQuery("q", "*:*", "fq", "Ea_b:true")); QueryRequest q2 = new QueryRequest(new SolrQuery("q", "*:*", "fq", "FB_b:true")); + String baseUrl; @Setup(Level.Trial) public void setupTrial(MiniClusterState.MiniClusterBenchState miniClusterState) @@ -100,9 +101,7 @@ public Boolean generate(SolrRandomnessSource in) { docs.field("FB_b", booleans); miniClusterState.index(COLLECTION, docs, 30 * 1000); - String base = miniClusterState.nodes.get(0); - q1.setBasePath(base); - q2.setBasePath(base); + baseUrl = miniClusterState.nodes.get(0); } @Setup(Level.Iteration) @@ -110,8 +109,7 @@ public void setupIteration(MiniClusterState.MiniClusterBenchState miniClusterSta throws SolrServerException, IOException { // Reload the collection/core to drop existing caches CollectionAdminRequest.Reload reload = CollectionAdminRequest.reloadCollection(COLLECTION); - reload.setBasePath(miniClusterState.nodes.get(0)); - miniClusterState.client.request(reload); + miniClusterState.client.requestWithBaseUrl(miniClusterState.nodes.get(0), null, reload); } @TearDown(Level.Iteration) @@ -139,14 +137,17 @@ public void dumpMetrics(MiniClusterState.MiniClusterBenchState miniClusterState) public Object filterCacheMultipleQueries( BenchState benchState, MiniClusterState.MiniClusterBenchState miniClusterState) throws SolrServerException, IOException { - return miniClusterState.client.request( - miniClusterState.getRandom().nextBoolean() ? benchState.q1 : benchState.q2, COLLECTION); + return miniClusterState.client.requestWithBaseUrl( + benchState.baseUrl, + COLLECTION, + miniClusterState.getRandom().nextBoolean() ? benchState.q1 : benchState.q2); } @Benchmark public Object filterCacheSingleQuery( BenchState benchState, MiniClusterState.MiniClusterBenchState miniClusterState) throws SolrServerException, IOException { - return miniClusterState.client.request(benchState.q1, COLLECTION); + return miniClusterState.client.requestWithBaseUrl( + benchState.baseUrl, COLLECTION, benchState.q1); } } diff --git a/solr/benchmark/src/java/org/apache/solr/bench/search/JsonFaceting.java b/solr/benchmark/src/java/org/apache/solr/bench/search/JsonFaceting.java index 498faed5814..1595de56d3b 100755 --- a/solr/benchmark/src/java/org/apache/solr/bench/search/JsonFaceting.java +++ b/solr/benchmark/src/java/org/apache/solr/bench/search/JsonFaceting.java @@ -180,11 +180,13 @@ public Object jsonFacet( BenchState state, BenchState.ThreadState threadState) throws Exception { + final var url = miniClusterState.nodes.get(threadState.random.nextInt(state.nodeCount)); QueryRequest queryRequest = new QueryRequest(state.params); - queryRequest.setBasePath( - miniClusterState.nodes.get(threadState.random.nextInt(state.nodeCount))); - - NamedList result = miniClusterState.client.request(queryRequest, state.collection); + NamedList result = + miniClusterState + .client + .requestWithBaseUrl(url, state.collection, queryRequest) + .getResponse(); // MiniClusterState.log("result: " + result); diff --git a/solr/benchmark/src/java/org/apache/solr/bench/search/NumericSearch.java b/solr/benchmark/src/java/org/apache/solr/bench/search/NumericSearch.java index 3c7a72385f9..4d662205230 100644 --- a/solr/benchmark/src/java/org/apache/solr/bench/search/NumericSearch.java +++ b/solr/benchmark/src/java/org/apache/solr/bench/search/NumericSearch.java @@ -101,8 +101,8 @@ public void setupTrial(MiniClusterState.MiniClusterBenchState miniClusterState) q.setParam("facet.field", "numbers_i_dv", "term_low_s", "term_high_s"); q.setParam("facet.limit", String.valueOf(maxCardinality)); QueryRequest req = new QueryRequest(q); - req.setBasePath(basePath); - QueryResponse response = req.process(miniClusterState.client, COLLECTION); + QueryResponse response = + miniClusterState.client.requestWithBaseUrl(basePath, COLLECTION, req); Set numbers = response.getFacetField("numbers_i_dv").getValues().stream() .map(FacetField.Count::getName) @@ -144,8 +144,7 @@ public void setupIteration(MiniClusterState.MiniClusterBenchState miniClusterSta throws SolrServerException, IOException { // Reload the collection/core to drop existing caches CollectionAdminRequest.Reload reload = CollectionAdminRequest.reloadCollection(COLLECTION); - reload.setBasePath(miniClusterState.nodes.get(0)); - miniClusterState.client.request(reload); + miniClusterState.client.requestWithBaseUrl(miniClusterState.nodes.get(0), null, reload); } public QueryRequest intSetQuery(boolean dvs) { @@ -172,7 +171,6 @@ QueryRequest setQuery(String field) { termQueryField + ":" + lowCardTerms.next(), "fq", "{!terms cache=false f='" + field + "'}" + queries.next())); - q.setBasePath(basePath); return q; } } diff --git a/solr/benchmark/src/java/org/apache/solr/bench/search/QueryResponseWriters.java b/solr/benchmark/src/java/org/apache/solr/bench/search/QueryResponseWriters.java index 15b4526d49e..111a1d6ac50 100644 --- a/solr/benchmark/src/java/org/apache/solr/bench/search/QueryResponseWriters.java +++ b/solr/benchmark/src/java/org/apache/solr/bench/search/QueryResponseWriters.java @@ -59,17 +59,7 @@ public class QueryResponseWriters { public static class BenchState { /** See {@link SolrCore#DEFAULT_RESPONSE_WRITERS} */ - @Param({ - CommonParams.JAVABIN, - CommonParams.JSON, - "cbor", - "smile", - "xml", - "python", - "phps", - "ruby", - "raw" - }) + @Param({CommonParams.JAVABIN, CommonParams.JSON, "cbor", "smile", "xml", "raw"}) String wt; private int docs = 100; @@ -98,7 +88,6 @@ public void setup(MiniClusterBenchState miniClusterState) throws Exception { q = new QueryRequest(params); q.setResponseParser(new NoOpResponseParser(wt)); String base = miniClusterState.nodes.get(0); - q.setBasePath(base); } } diff --git a/solr/benchmark/src/java/org/apache/solr/bench/search/SimpleSearch.java b/solr/benchmark/src/java/org/apache/solr/bench/search/SimpleSearch.java index 165d68ecb3b..46982b33b89 100644 --- a/solr/benchmark/src/java/org/apache/solr/bench/search/SimpleSearch.java +++ b/solr/benchmark/src/java/org/apache/solr/bench/search/SimpleSearch.java @@ -65,8 +65,6 @@ public void setupTrial(MiniClusterState.MiniClusterBenchState miniClusterState) miniClusterState.setUseHttp1(useHttp1); miniClusterState.startMiniCluster(1); miniClusterState.createCollection(COLLECTION, 1, 1); - String base = miniClusterState.nodes.get(0); - q.setBasePath(base); } @Setup(Level.Iteration) @@ -74,7 +72,6 @@ public void setupIteration(MiniClusterState.MiniClusterBenchState miniClusterSta throws SolrServerException, IOException { // Reload the collection/core to drop existing caches CollectionAdminRequest.Reload reload = CollectionAdminRequest.reloadCollection(COLLECTION); - reload.setBasePath(miniClusterState.nodes.get(0)); miniClusterState.client.request(reload); total = new AtomicLong(); diff --git a/solr/benchmark/src/test/org/apache/solr/bench/MiniClusterBenchStateTest.java b/solr/benchmark/src/test/org/apache/solr/bench/MiniClusterBenchStateTest.java index e17ed29dcd8..af568e3bb98 100644 --- a/solr/benchmark/src/test/org/apache/solr/bench/MiniClusterBenchStateTest.java +++ b/solr/benchmark/src/test/org/apache/solr/bench/MiniClusterBenchStateTest.java @@ -118,10 +118,7 @@ public void testMiniClusterState() throws Exception { miniBenchState.forceMerge(collection, 15); ModifiableSolrParams params = MiniClusterState.params("q", "*:*"); - QueryRequest queryRequest = new QueryRequest(params); - queryRequest.setBasePath(miniBenchState.nodes.get(0)); - QueryResponse result = queryRequest.process(miniBenchState.client, collection); BaseBenchState.log("match all query result=" + result); diff --git a/solr/bin/solr b/solr/bin/solr index 8a993233a0a..f51011444e1 100755 --- a/solr/bin/solr +++ b/solr/bin/solr @@ -51,7 +51,7 @@ verbose=false THIS_OS=$(uname -s) # What version of Java is required to run this version of Solr. -JAVA_VER_REQ=11 +JAVA_VER_REQ=21 stop_all=false @@ -369,7 +369,7 @@ function print_usage() { echo "" echo "Usage: solr $CMD [-f] [--user-managed] [--host host] [-p port] [--server-dir directory] [-z zkHost] [-m memory] [-e example] [--solr-home solr.solr.home] [--data-home solr.data.home] [--jvm-opts \"jvm-opts\"] [--verbose]" echo "" - echo " -f Start Solr in foreground; default starts Solr in the background" + echo " -f/--foreground Start Solr in foreground; default starts Solr in the background" echo " and sends stdout / stderr to solr-PORT-console.log" echo "" echo " --user-managed Start Solr in user managed aka standalone mode" @@ -403,7 +403,7 @@ function print_usage() { echo " --data-home Sets the solr.data.home system property, where Solr will store index data in /data subdirectories." echo " If not set, Solr uses solr.solr.home for config and data." echo "" - echo " -e Name of the example to run; available examples:" + echo " -e/--example Name of the example to run; available examples:" echo " cloud: SolrCloud example" echo " techproducts: Comprehensive example illustrating many of Solr's core capabilities" echo " schemaless: Schema-less example (schema is inferred from data during indexing)" @@ -419,7 +419,7 @@ function print_usage() { echo " you could pass: -j \"--include-jetty-dir=/etc/jetty/custom/server/\"" echo " In most cases, you should wrap the additional parameters in double quotes." echo "" - echo " --no-prompt Don't prompt for input; accept all defaults when running examples that accept user input" + echo " -y/--no-prompt Don't prompt for input; accept all defaults when running examples that accept user input" echo "" echo " --force If attempting to start Solr as the root user, the script will exit with a warning that running Solr as \"root\" can cause problems." echo " It is possible to override this warning with the '--force' parameter." @@ -493,55 +493,13 @@ function run_tool() { # shellcheck disable=SC2086 "$JAVA" $SOLR_SSL_OPTS $AUTHC_OPTS ${SOLR_ZK_CREDS_AND_ACLS:-} ${SOLR_TOOL_OPTS:-} -Dsolr.install.dir="$SOLR_TIP" \ - -Dlog4j.configurationFile="$DEFAULT_SERVER_DIR/resources/log4j2-console.xml" \ + -Dlog4j.configurationFile="$DEFAULT_SERVER_DIR/resources/log4j2-console.xml" -Dsolr.pid.dir="$SOLR_PID_DIR" \ -classpath "$DEFAULT_SERVER_DIR/solr-webapp/webapp/WEB-INF/lib/*:$DEFAULT_SERVER_DIR/lib/ext/*:$DEFAULT_SERVER_DIR/lib/*" \ org.apache.solr.cli.SolrCLI "$@" return $? } # end run_tool function -# get status about any Solr nodes running on this host -function get_status() { - # first, see if Solr is running - numSolrs=$(find "$SOLR_PID_DIR" -name "solr-*.pid" -type f | wc -l | tr -d ' ') - if [ "$numSolrs" != "0" ]; then - echo -e "\nFound $numSolrs Solr nodes: " - while read PIDF - do - ID=$(cat "$PIDF") - port=$(jetty_port "$ID") - if [ "$port" != "" ]; then - echo -e "\nSolr process $ID running on port $port" - run_tool status --solr-url "$SOLR_URL_SCHEME://$SOLR_TOOL_HOST:$port" "$@" - echo "" - else - echo -e "\nSolr process $ID from $PIDF not found." - fi - done < <(find "$SOLR_PID_DIR" -name "solr-*.pid" -type f) - else - # no pid files but check using ps just to be sure - numSolrs=$(ps auxww | grep start\.jar | grep solr\.solr\.home | grep -v grep | wc -l | sed -e 's/^[ \t]*//') - if [ "$numSolrs" != "0" ]; then - echo -e "\nFound $numSolrs Solr nodes: " - PROCESSES=$(ps auxww | grep start\.jar | grep solr\.solr\.home | grep -v grep | awk '{print $2}' | sort -r) - for ID in $PROCESSES - do - port=$(jetty_port "$ID") - if [ "$port" != "" ]; then - echo "" - echo "Solr process $ID running on port $port" - run_tool status --solr-url "$SOLR_URL_SCHEME://$SOLR_TOOL_HOST:$port" "$@" - echo "" - fi - done - else - echo -e "\nNo Solr nodes are running.\n" - run_tool status "$@" - fi - fi - -} # end get_status - # tries to gracefully stop Solr using the Jetty # stop command and if that fails, then uses kill -9 # (will attempt to thread dump before killing) @@ -616,7 +574,7 @@ function stop_solr() { if [ $# -eq 1 ]; then case $1 in - --help|-h|-help) + --help|-h) run_tool "" exit ;; @@ -632,12 +590,6 @@ else exit fi -# status tool -if [ "$SCRIPT_CMD" == "status" ]; then - get_status - exit $? -fi - # configure authentication if [[ "$SCRIPT_CMD" == "auth" ]]; then : "${SOLR_SERVER_DIR:=$DEFAULT_SERVER_DIR}" @@ -742,7 +694,7 @@ if [ $# -gt 0 ]; then PASS_TO_RUN_EXAMPLE+=("--user-managed") shift ;; - -d|--dir|-dir|--server-dir) + --server-dir) if [[ -z "$2" || "${2:0:1}" == "-" ]]; then print_usage "$SCRIPT_CMD" "Server directory is required when using the $1 option!" exit 1 @@ -762,7 +714,7 @@ if [ $# -gt 0 ]; then SOLR_SERVER_DIR="$(cd "$SOLR_SERVER_DIR" || (echo "SOLR_SERVER_DIR not found" && exit 1); pwd)" shift 2 ;; - -s|--solr-home|-solr.home) + --solr-home) if [[ -z "$2" || "${2:0:1}" == "-" ]]; then print_usage "$SCRIPT_CMD" "Solr home directory is required when using the $1 option!" exit 1 @@ -771,11 +723,15 @@ if [ $# -gt 0 ]; then SOLR_HOME="$2" shift 2 ;; - -t|--data-home|-data.home) + --data-home) + if [[ -z "$2" || "${2:0:1}" == "-" ]]; then + print_usage "$SCRIPT_CMD" "Data home directory is required when using the $1 option!" + exit 1 + fi SOLR_DATA_HOME="$2" shift 2 ;; - -e|--example|-example) + -e|--example) if [[ -z "$2" || "${2:0:1}" == "-" ]]; then print_usage "$SCRIPT_CMD" "Example name is required when using the $1 option!" exit 1 @@ -783,11 +739,11 @@ if [ $# -gt 0 ]; then EXAMPLE="$2" shift 2 ;; - -f|--foreground|-foreground) + -f|--foreground) FG="true" shift ;; - --host|-host) + --host) if [[ -z "$2" || "${2:0:1}" == "-" ]]; then print_usage "$SCRIPT_CMD" "Hostname is required when using the $1 option!" exit 1 @@ -796,7 +752,7 @@ if [ $# -gt 0 ]; then PASS_TO_RUN_EXAMPLE+=("--host" "$SOLR_HOST") shift 2 ;; - -m|--memory|-memory) + -m|--memory) if [[ -z "$2" || "${2:0:1}" == "-" ]]; then print_usage "$SCRIPT_CMD" "Memory setting is required when using the $1 option!" exit 1 @@ -805,7 +761,7 @@ if [ $# -gt 0 ]; then PASS_TO_RUN_EXAMPLE+=("-m" "$SOLR_HEAP") shift 2 ;; - -p|--port|-port) + -p|--port) if [[ -z "$2" || "${2:0:1}" == "-" ]]; then print_usage "$SCRIPT_CMD" "Port number is required when using the $1 option!" exit 1 @@ -815,7 +771,7 @@ if [ $# -gt 0 ]; then PASS_TO_RUN_EXAMPLE+=("-p" "$SOLR_PORT") shift 2 ;; - -z|--zk-host|-zkHost|--zkHost) + -z|--zk-host) if [[ -z "$2" || "${2:0:1}" == "-" ]]; then print_usage "$SCRIPT_CMD" "Zookeeper connection string is required when using the $1 option!" exit 1 @@ -824,7 +780,7 @@ if [ $# -gt 0 ]; then PASS_TO_RUN_EXAMPLE+=("-z" "$ZK_HOST") shift 2 ;; - -a|--jvm-opts|-addlopts) + --jvm-opts) if [[ -z "$2" ]]; then print_usage "$SCRIPT_CMD" "JVM options are required when using the $1 option!" exit 1 @@ -833,16 +789,15 @@ if [ $# -gt 0 ]; then PASS_TO_RUN_EXAMPLE+=("--jvm-opts" "$ADDITIONAL_CMD_OPTS") shift 2 ;; - -j|--jettyconfig|-jettyconfig) + -j|--jettyconfig) if [[ -z "$2" || "${2:0:1}" == "-" ]]; then print_usage "$SCRIPT_CMD" "Jetty config is required when using the $1 option!" exit 1 fi ADDITIONAL_JETTY_CONFIG="$2" - PASS_TO_RUN_EXAMPLE+=("-j" "$ADDITIONAL_JETTY_CONFIG") shift 2 ;; - -k|--key|-key) + -k|--key) if [[ -z "$2" || "${2:0:1}" == "-" ]]; then print_usage "$SCRIPT_CMD" "Stop key is required when using the $1 option!" exit 1 @@ -850,15 +805,15 @@ if [ $# -gt 0 ]; then STOP_KEY="$2" shift 2 ;; - -h|--help|-help) + -h|--help) print_usage "$SCRIPT_CMD" exit 0 ;; - --noprompt|-noprompt|--no-prompt) + -y|--no-prompt) PASS_TO_RUN_EXAMPLE+=("--no-prompt") shift ;; - -V|--verbose|-verbose|-v) + --verbose) verbose=true SOLR_LOG_LEVEL=DEBUG PASS_TO_RUN_EXAMPLE+=("--verbose") @@ -868,11 +823,11 @@ if [ $# -gt 0 ]; then SOLR_LOG_LEVEL=WARN shift ;; - --all|-all) + --all) stop_all=true shift ;; - --force|-force) + --force) FORCE=true PASS_TO_RUN_EXAMPLE+=("--force") shift @@ -1078,8 +1033,7 @@ if [ "${SOLR_HOME:0:${#EXAMPLE_DIR}}" = "$EXAMPLE_DIR" ]; then SOLR_LOGS_DIR="$SOLR_HOME/../logs" fi -# Set the logging manager by default, so that Lucene JUL logs are included with Solr logs. -LOG4J_CONFIG=("-Djava.util.logging.manager=org.apache.logging.log4j.jul.LogManager") +LOG4J_CONFIG=() if [ -n "${LOG4J_PROPS:-}" ]; then LOG4J_CONFIG+=("-Dlog4j.configurationFile=$LOG4J_PROPS") fi @@ -1102,31 +1056,13 @@ fi # Establish default GC logging opts if no env var set (otherwise init to sensible default) if [ -z "${GC_LOG_OPTS}" ]; then - if [[ "$JAVA_VER_NUM" -lt "9" ]] ; then - GC_LOG_OPTS=('-verbose:gc' '-XX:+PrintHeapAtGC' '-XX:+PrintGCDetails' \ - '-XX:+PrintGCDateStamps' '-XX:+PrintGCTimeStamps' '-XX:+PrintTenuringDistribution' \ - '-XX:+PrintGCApplicationStoppedTime') - else - GC_LOG_OPTS=('-Xlog:gc*') - fi -else - # TODO: Should probably not overload GC_LOG_OPTS as both string and array, but leaving it be for now - # shellcheck disable=SC2128 - GC_LOG_OPTS=($GC_LOG_OPTS) + GC_LOG_OPTS=('-Xlog:gc*') fi # if verbose gc logging enabled, setup the location of the log file and rotation if [ "${#GC_LOG_OPTS[@]}" -gt 0 ]; then - if [[ "$JAVA_VER_NUM" -lt "9" ]] || [ "$JAVA_VENDOR" == "OpenJ9" ]; then - gc_log_flag="-Xloggc" - if [ "$JAVA_VENDOR" == "OpenJ9" ]; then - gc_log_flag="-Xverbosegclog" - fi - if [ -z ${JAVA8_GC_LOG_FILE_OPTS+x} ]; then - GC_LOG_OPTS+=("$gc_log_flag:$SOLR_LOGS_DIR/solr_gc.log" '-XX:+UseGCLogFileRotation' '-XX:NumberOfGCLogFiles=9' '-XX:GCLogFileSize=20M') - else - GC_LOG_OPTS+=($JAVA8_GC_LOG_FILE_OPTS) - fi + if [ "$JAVA_VENDOR" == "OpenJ9" ]; then + GC_LOG_OPTS+=("-Xverbosegclog:$SOLR_LOGS_DIR/solr_gc.log" '-XX:+UseGCLogFileRotation' '-XX:NumberOfGCLogFiles=9' '-XX:GCLogFileSize=20M') else # https://openjdk.java.net/jeps/158 for i in "${!GC_LOG_OPTS[@]}"; @@ -1370,18 +1306,8 @@ function start_solr() { exit 1 fi - # Workaround for JIT crash, see https://issues.apache.org/jira/browse/SOLR-16463 - if [[ "$JAVA_VER_NUM" -ge "17" ]] ; then - SCRIPT_SOLR_OPTS+=("-XX:CompileCommand=exclude,com.github.benmanes.caffeine.cache.BoundedLocalCache::put") - echo "Java $JAVA_VER_NUM detected. Enabled workaround for SOLR-16463" - fi - - # Vector optimizations are only supported for Java 20 and 21 for now. - # This will need to change as Lucene is upgraded and newer Java versions are released - if [[ "$JAVA_VER_NUM" -ge "20" ]] && [[ "$JAVA_VER_NUM" -le "21" ]] ; then - SCRIPT_SOLR_OPTS+=("--add-modules" "jdk.incubator.vector") - echo "Java $JAVA_VER_NUM detected. Incubating Panama Vector APIs have been enabled" - fi + # Add vector optimizations module + SCRIPT_SOLR_OPTS+=("--add-modules" "jdk.incubator.vector") SOLR_START_OPTS=('-server' "${JAVA_MEM_OPTS[@]}" "${GC_TUNE_ARR[@]}" "${GC_LOG_OPTS[@]}" "${IP_ACL_OPTS[@]}" \ "${REMOTE_JMX_OPTS[@]}" "${CLOUD_MODE_OPTS[@]}" -Dsolr.log.dir="$SOLR_LOGS_DIR" \ diff --git a/solr/bin/solr.cmd b/solr/bin/solr.cmd index f4f3d927fc0..5fd6ec44aea 100755 --- a/solr/bin/solr.cmd +++ b/solr/bin/solr.cmd @@ -20,6 +20,8 @@ IF "%OS%"=="Windows_NT" setlocal enabledelayedexpansion enableextensions +@REM What version of Java is required to run this version of Solr. +set REQUIRED_JAVA_VERSION=21 set "PASS_TO_RUN_EXAMPLE=" REM Determine top-level Solr directory @@ -52,7 +54,11 @@ IF NOT DEFINED JAVA_HOME ( set "JAVA_HOME=%%B" ) ) -IF NOT DEFINED JAVA_HOME goto need_java_home +IF NOT DEFINED JAVA_HOME ( + REM Need java home + @echo "Please set the JAVA_HOME environment variable to the path where you installed Java !REQUIRED_JAVA_VERSION!+" + goto done +) set JAVA_HOME=%JAVA_HOME:"=% IF %JAVA_HOME:~-1%==\ SET JAVA_HOME=%JAVA_HOME:~0,-1% IF NOT EXIST "%JAVA_HOME%\bin\java.exe" ( @@ -61,8 +67,8 @@ IF NOT EXIST "%JAVA_HOME%\bin\java.exe" ( ) set "JAVA=%JAVA_HOME%\bin\java" CALL :resolve_java_info -IF !JAVA_MAJOR_VERSION! LSS 8 ( - set "SCRIPT_ERROR=Java 1.8 or later is required to run Solr. Current Java version is: !JAVA_VERSION_INFO! (detected major: !JAVA_MAJOR_VERSION!)" +IF !JAVA_MAJOR_VERSION! LSS !REQUIRED_JAVA_VERSION! ( + set "SCRIPT_ERROR=Java !REQUIRED_JAVA_VERSION! or later is required to run Solr. Current Java version is: !JAVA_VERSION_INFO! (detected major: !JAVA_MAJOR_VERSION!)" goto err ) @@ -242,74 +248,42 @@ IF "%SOLR_JETTY_HOST%"=="" ( set "SOLR_JETTY_HOST=127.0.0.1" ) -set FIRST_ARG=%1 - -IF [%1]==[] goto usage - -REM -help is a special case to faciliate folks learning about how to use Solr. -IF "%1"=="-help" goto run_solrcli -IF "%1"=="-usage" goto run_solrcli -IF "%1"=="-h" goto run_solrcli -IF "%1"=="--help" goto run_solrcli -IF "%1"=="-help" goto run_solrcli -IF "%1"=="/?" goto run_solrcli -IF "%1"=="status" goto get_status -IF "%1"=="version" goto run_solrcli -IF "%1"=="-v" goto run_solrcli -IF "%1"=="-version" goto run_solrcli -IF "%1"=="assert" goto run_solrcli -IF "%1"=="zk" goto run_solrcli -IF "%1"=="export" goto run_solrcli -IF "%1"=="package" goto run_solrcli -IF "%1"=="auth" goto run_solrcli -IF "%1"=="api" goto run_solrcli -IF "%1"=="post" goto run_solrcli - -REM Only allow the command to be the first argument, assume start if not supplied + +REM Handle special commands IF "%1"=="start" goto set_script_cmd IF "%1"=="stop" goto set_script_cmd IF "%1"=="restart" goto set_script_cmd -IF "%1"=="healthcheck" goto run_solrcli -IF "%1"=="create" goto run_solrcli -IF "%1"=="delete" goto run_solrcli -IF "%1"=="postlogs" goto run_solrcli +IF "%1"=="auth" goto set_script_cmd -IF "%1"=="auth" ( - set SCRIPT_CMD=auth - SHIFT - goto run_auth +REM Handle all other commands by simply running SolrCLI +"%JAVA%" %SOLR_SSL_OPTS% %AUTHC_OPTS% %SOLR_ZK_CREDS_AND_ACLS% %SOLR_TOOL_OPTS% -Dsolr.install.dir="%SOLR_TIP%" ^ + -Dlog4j.configurationFile="file:///%DEFAULT_SERVER_DIR%\resources\log4j2-console.xml" ^ + -classpath "%DEFAULT_SERVER_DIR%\solr-webapp\webapp\WEB-INF\lib\*;%DEFAULT_SERVER_DIR%\lib\ext\*" ^ + org.apache.solr.cli.SolrCLI %* +if errorlevel 1 ( + exit /b 1 ) -IF "%1"=="config" goto run_solrcli +goto done +:set_script_cmd +set SCRIPT_CMD=%1 +SHIFT +IF "%SCRIPT_CMD%"=="auth" goto run_auth goto parse_args :usage IF NOT "%SCRIPT_ERROR%"=="" ECHO %SCRIPT_ERROR% -IF [%FIRST_ARG%]==[] goto run_solrcli -IF "%FIRST_ARG%"=="-help" goto run_solrcli -IF "%FIRST_ARG%"=="-usage" goto run_solrcli -IF "%FIRST_ARG%"=="-h" goto run_solrcli -IF "%FIRST_ARG%"=="--help" goto run_solrcli -IF "%FIRST_ARG%"=="/?" goto run_solrcli IF "%SCRIPT_CMD%"=="start" goto start_usage IF "%SCRIPT_CMD%"=="restart" goto start_usage IF "%SCRIPT_CMD%"=="stop" goto stop_usage -IF "%SCRIPT_CMD%"=="healthcheck" goto run_solrcli -IF "%SCRIPT_CMD%"=="create" goto run_solrcli -IF "%SCRIPT_CMD%"=="delete" goto run_solrcli -IF "%SCRIPT_CMD%"=="cluster" goto run_solrcli -IF "%SCRIPT_CMD%"=="zk" goto run_solrcli -IF "%SCRIPT_CMD%"=="auth" goto run_solrcli -IF "%SCRIPT_CMD%"=="package" goto run_solrcli -IF "%SCRIPT_CMD%"=="status" goto run_solrcli -IF "%SCRIPT_CMD%"=="postlogs" goto run_solrcli -goto done +REM Should not be reachable, but just in case +goto err :start_usage @echo. @echo Usage: solr %SCRIPT_CMD% [-f] [--user-managed] [--host hostname] [-p port] [--server-dir directory] [-z zkHost] [-m memory] [-e example] [--solr-home solr.solr.home] [--data-home solr.data.home] [--jvm-opts "jvm-opts"] [--verbose] @echo. -@echo -f Start Solr in foreground; default starts Solr in the background +@echo -f/--foreground Start Solr in foreground; default starts Solr in the background @echo and sends stdout / stderr to solr-PORT-console.log @echo. @echo --user-managed Start Solr in user managed aka standalone mode" @@ -317,7 +291,7 @@ goto done @echo. @echo --host host Specify the hostname for this Solr instance @echo. -@echo -p port Specify the port to start the Solr HTTP listener on; default is 8983 +@echo -p/--port port Specify the port to start the Solr HTTP listener on; default is 8983 @echo The specified port (SOLR_PORT) will also be used to determine the stop port @echo STOP_PORT=(%%SOLR_PORT%%-1000) and JMX RMI listen port RMI_PORT=(%%SOLR_PORT%%+10000). @echo For instance, if you set -p 8985, then the STOP_PORT=7985 and RMI_PORT=18985 @@ -329,10 +303,10 @@ goto done @echo an embedded ZooKeeper instance will be launched. @echo Set the ZK_CREATE_CHROOT environment variable to true if your ZK host has a chroot path, and you want to create it automatically." @echo. -@echo -m memory Sets the min (-Xms) and max (-Xmx) heap size for the JVM, such as: -m 4g +@echo -m/--memory memory Sets the min (-Xms) and max (-Xmx) heap size for the JVM, such as: -m 4g @echo results in: -Xms4g -Xmx4g; by default, this script sets the heap size to 512m @echo. -@echo --solr.home dir Sets the solr.solr.home system property; Solr will create core directories under +@echo --solr-home dir Sets the solr.solr.home system property; Solr will create core directories under @echo this directory. This allows you to run multiple Solr instances on the same host @echo while reusing the same server directory set using the --server-dir parameter. If set, the @echo specified directory should contain a solr.xml file, unless solr.xml exists in Zookeeper. @@ -343,7 +317,7 @@ goto done @echo --data-home dir Sets the solr.data.home system property, where Solr will store index data in ^/data subdirectories. @echo If not set, Solr uses solr.solr.home for both config and data. @echo. -@echo -e example Name of the example to run; available examples: +@echo -e/--example name Name of the example to run; available examples: @echo cloud: SolrCloud example @echo techproducts: Comprehensive example illustrating many of Solr's core capabilities @echo schemaless: Schema-less example (schema is inferred from data during indexing) @@ -359,7 +333,7 @@ goto done @echo you could pass: -j "--include-jetty-dir=/etc/jetty/custom/server/" @echo In most cases, you should wrap the additional parameters in double quotes. @echo. -@echo --no-prompt Don't prompt for input; accept all defaults when running examples that accept user input +@echo -y/--no-prompt Don't prompt for input; accept all defaults when running examples that accept user input @echo. @echo --verbose and -q/--quiet Verbose or quiet logging. Sets default log level to DEBUG or WARN instead of INFO @echo. @@ -381,67 +355,67 @@ goto done @echo. goto done - -REM Really basic command-line arg parsing +REM Parse arguments for special commands (start, stop, restart) :parse_args set "arg=%~1" set "firstTwo=%arg:~0,2%" -IF "%SCRIPT_CMD%"=="" set SCRIPT_CMD=start -IF [%1]==[] goto process_script_cmd -IF "%1"=="-help" goto usage -IF "%1"=="-h" goto usage -IF "%1"=="-usage" goto usage -IF "%1"=="/?" goto usage + +REM In case no arguments left, run special command +IF [%1]==[] goto run_special_command + +REM Skip start / restart arguments if stop command +IF "%SCRIPT_CMD%"=="stop" goto parse_stop_args + +:parse_start_args IF "%1"=="-f" goto set_foreground_mode IF "%1"=="--foreground" goto set_foreground_mode -IF "%1"=="-V" goto set_verbose IF "%1"=="--verbose" goto set_verbose -IF "%1"=="-v" goto set_verbose IF "%1"=="-q" goto set_warn IF "%1"=="--quiet" goto set_warn IF "%1"=="--user-managed" goto set_user_managed_mode -IF "%1"=="-d" goto set_server_dir -IF "%1"=="--dir" goto set_server_dir IF "%1"=="--server-dir" goto set_server_dir -IF "%1"=="-s" goto set_solr_home_dir IF "%1"=="--solr-home" goto set_solr_home_dir -IF "%1"=="-t" goto set_solr_data_dir -IF "%1"=="--solr-data" goto set_solr_data_dir IF "%1"=="--data-home" goto set_solr_data_dir IF "%1"=="-e" goto set_example IF "%1"=="--example" goto set_example IF "%1"=="--host" goto set_host IF "%1"=="-m" goto set_memory IF "%1"=="--memory" goto set_memory -IF "%1"=="-p" goto set_port -IF "%1"=="--port" goto set_port IF "%1"=="-z" goto set_zookeeper IF "%1"=="--zk-host" goto set_zookeeper -IF "%1"=="-zkHost" goto set_zookeeper -IF "%1"=="--zkHost" goto set_zookeeper IF "%1"=="-s" goto set_solr_url IF "%1"=="--solr-url" goto set_solr_url -IF "%1"=="-solrUrl" goto set_solr_url -IF "%1"=="-a" goto set_jvm_opts IF "%1"=="--jvm-opts" goto set_jvm_opts IF "%1"=="-j" goto set_addl_jetty_config IF "%1"=="--jettyconfig" goto set_addl_jetty_config -IF "%1"=="--noprompt" goto set_noprompt +IF "%1"=="-y" goto set_noprompt IF "%1"=="--no-prompt" goto set_noprompt + +REM Skip stop arg parsing if not stop command +IF NOT "%SCRIPT_CMD%"=="stop" goto parse_general_args + +:parse_stop_args IF "%1"=="-k" goto set_stop_key IF "%1"=="--key" goto set_stop_key IF "%1"=="--all" goto set_stop_all -IF "%1"=="-all" goto set_stop_all + +:parse_general_args + +REM Print usage of command in case help option included +IF "%1"=="--help" goto usage +IF "%1"=="-h" goto usage + +REM other args supported by all special commands +IF "%1"=="-p" goto set_port +IF "%1"=="--port" goto set_port IF "%firstTwo%"=="-D" goto set_passthru + +REM Argument not supported / found IF NOT "%1"=="" goto invalid_cmd_line +REM Not reachable, but just in case goto invalid_cmd_line -:set_script_cmd -set SCRIPT_CMD=%1 -SHIFT -goto parse_args - :set_foreground_mode set FG=1 SHIFT @@ -691,8 +665,27 @@ set "PASS_TO_RUN_EXAMPLE=--no-prompt !PASS_TO_RUN_EXAMPLE!" SHIFT goto parse_args -REM Perform the requested command after processing args -:process_script_cmd +REM Handle invalid arguments passed to special commands (start, stop, restart) +:invalid_cmd_line +@echo. +IF "!SCRIPT_ERROR!"=="" ( + @echo Invalid command-line option: %1 +) ELSE ( + @echo ERROR: !SCRIPT_ERROR! +) +@echo. +IF "%SCRIPT_CMD%"=="start" ( + goto start_usage +) ELSE IF "%SCRIPT_CMD%"=="restart" ( + goto start_usage +) ELSE IF "%SCRIPT_CMD%"=="stop" ( + goto stop_usage +) +REM Not reachable, but just in case +goto err + +REM Process special commands (start, stop, restart) +:run_special_command IF "%verbose%"=="1" ( CALL :safe_echo "Using Solr root directory: %SOLR_TIP%" @@ -733,36 +726,20 @@ IF NOT EXIST "%SOLR_SERVER_DIR%" ( goto err ) -IF NOT "%EXAMPLE%"=="" goto run_example - -:start_solr -IF "%SOLR_HOME%"=="" set "SOLR_HOME=%SOLR_SERVER_DIR%\solr" -IF EXIST "%cd%\%SOLR_HOME%" set "SOLR_HOME=%cd%\%SOLR_HOME%" - -IF NOT EXIST "%SOLR_HOME%\" ( - IF EXIST "%SOLR_SERVER_DIR%\%SOLR_HOME%" ( - set "SOLR_HOME=%SOLR_SERVER_DIR%\%SOLR_HOME%" - ) ELSE ( - set "SCRIPT_ERROR=Solr home directory %SOLR_HOME% not found!" - goto err - ) -) - IF "%STOP_KEY%"=="" set STOP_KEY=solrrocks -@REM This is quite hacky, but examples rely on a different log4j2.xml -@REM so that we can write logs for examples to %SOLR_HOME%\..\logs -IF [%SOLR_LOGS_DIR%] == [] ( - set "SOLR_LOGS_DIR=%SOLR_SERVER_DIR%\logs" -) ELSE ( - set SOLR_LOGS_DIR=%SOLR_LOGS_DIR:"=% -) +IF NOT "%EXAMPLE%"=="" ( + REM Run the requested example -set "EXAMPLE_DIR=%SOLR_TIP%\example" -set TMP_SOLR_HOME=!SOLR_HOME:%EXAMPLE_DIR%=! -IF NOT "%TMP_SOLR_HOME%"=="%SOLR_HOME%" ( - set "SOLR_LOGS_DIR=%SOLR_HOME%\..\logs" - set "LOG4J_CONFIG=%SOLR_SERVER_DIR%\resources\log4j2.xml" + "%JAVA%" %SOLR_SSL_OPTS% %AUTHC_OPTS% %SOLR_ZK_CREDS_AND_ACLS% %SOLR_TOOL_OPTS% -Dsolr.install.dir="%SOLR_TIP%" ^ + -Dlog4j.configurationFile="file:///%DEFAULT_SERVER_DIR%\resources\log4j2-console.xml" ^ + -Dsolr.install.symDir="%SOLR_TIP%" ^ + -classpath "%DEFAULT_SERVER_DIR%\solr-webapp\webapp\WEB-INF\lib\*;%DEFAULT_SERVER_DIR%\lib\ext\*" ^ + org.apache.solr.cli.SolrCLI run_example --script "%SDIR%\solr.cmd" -e %EXAMPLE% --server-dir "%SOLR_SERVER_DIR%" ^ + --url-scheme !SOLR_URL_SCHEME! !PASS_TO_RUN_EXAMPLE! + + REM End of run_example + goto done ) set IS_RESTART=0 @@ -775,77 +752,112 @@ IF "%SCRIPT_CMD%"=="restart" ( set IS_RESTART=1 ) +REM Skipt to start if not stop or restart (that executes stop first) +IF "%SCRIPT_CMD%"=="start" goto start_solr + @REM stop logic here +:stop_solr IF "%SOLR_STOP_WAIT%"=="" ( set SOLR_STOP_WAIT=180 ) -IF "%SCRIPT_CMD%"=="stop" ( - IF "%SOLR_PORT%"=="" ( - IF "%STOP_ALL%"=="1" ( - set found_it=0 - for /f "usebackq" %%i in (`dir /b "%SOLR_TIP%\bin" ^| findstr /i "^solr-.*\.port$"`) do ( - set SOME_SOLR_PORT= - For /F "delims=" %%J In ('type "%SOLR_TIP%\bin\%%i"') do set SOME_SOLR_PORT=%%~J - if NOT "!SOME_SOLR_PORT!"=="" ( - for /f "tokens=2,5" %%j in ('netstat -aon ^| find "TCP " ^| find ":0 " ^| find ":!SOME_SOLR_PORT! "') do ( - @REM j is the ip:port and k is the pid - IF NOT "%%k"=="0" ( - IF "%%j"=="%SOLR_JETTY_HOST%:!SOME_SOLR_PORT!" ( - set found_it=1 - @echo Stopping Solr process %%k running on port !SOME_SOLR_PORT! - IF "%STOP_PORT%"=="" ( - set /A LOCAL_STOP_PORT=!SOME_SOLR_PORT! - 1000 - ) else ( - set LOCAL_STOP_PORT=%STOP_PORT% - ) - "%JAVA%" %SOLR_SSL_OPTS% -Djetty.home="%SOLR_SERVER_DIR%" -jar "%SOLR_SERVER_DIR%\start.jar" STOP.PORT=!LOCAL_STOP_PORT! STOP.KEY=%STOP_KEY% --stop - del "%SOLR_TIP%"\bin\solr-!SOME_SOLR_PORT!.port - REM wait for the process to terminate - CALL :wait_for_process_exit %%k !SOLR_STOP_WAIT! - REM Kill it if it is still running after the graceful shutdown - IF EXIST "%JAVA_HOME%\bin\jstack.exe" ( - qprocess "%%k" >nul 2>nul && "%JAVA_HOME%\bin\jstack.exe" %%k && taskkill /f /PID %%k - ) else ( - qprocess "%%k" >nul 2>nul && taskkill /f /PID %%k - ) +IF "%SOLR_PORT%"=="" ( + IF "%STOP_ALL%"=="1" ( + REM Stop all running Solr instances + set found_it=0 + for /f "usebackq" %%i in (`dir /b "%SOLR_TIP%\bin" ^| findstr /i "^solr-.*\.port$"`) do ( + set SOME_SOLR_PORT= + For /F "delims=" %%J In ('type "%SOLR_TIP%\bin\%%i"') do set SOME_SOLR_PORT=%%~J + if NOT "!SOME_SOLR_PORT!"=="" ( + for /f "tokens=2,5" %%j in ('netstat -aon ^| find "TCP " ^| find ":0 " ^| find ":!SOME_SOLR_PORT! "') do ( + @REM j is the ip:port and k is the pid + IF NOT "%%k"=="0" ( + IF "%%j"=="%SOLR_JETTY_HOST%:!SOME_SOLR_PORT!" ( + set found_it=1 + @echo Stopping Solr process %%k running on port !SOME_SOLR_PORT! + IF "%STOP_PORT%"=="" ( + set /A LOCAL_STOP_PORT=!SOME_SOLR_PORT! - 1000 + ) else ( + set LOCAL_STOP_PORT=%STOP_PORT% + ) + "%JAVA%" %SOLR_SSL_OPTS% -Djetty.home="%SOLR_SERVER_DIR%" -jar "%SOLR_SERVER_DIR%\start.jar" STOP.PORT=!LOCAL_STOP_PORT! STOP.KEY=%STOP_KEY% --stop + del "%SOLR_TIP%"\bin\solr-!SOME_SOLR_PORT!.port + REM wait for the process to terminate + CALL :wait_for_process_exit %%k !SOLR_STOP_WAIT! + REM Kill it if it is still running after the graceful shutdown + IF EXIST "%JAVA_HOME%\bin\jstack.exe" ( + qprocess "%%k" >nul 2>nul && "%JAVA_HOME%\bin\jstack.exe" %%k && taskkill /f /PID %%k + ) else ( + qprocess "%%k" >nul 2>nul && taskkill /f /PID %%k ) ) ) ) ) - if "!found_it!"=="0" echo No Solr nodes found to stop. - ) ELSE ( - set "SCRIPT_ERROR=Must specify the port when trying to stop Solr, or use --all to stop all running nodes on this host." - goto err ) + if "!found_it!"=="0" echo No Solr nodes found to stop. ) ELSE ( - set found_it=0 - For /f "tokens=2,5" %%M in ('netstat -nao ^| find "TCP " ^| find ":0 " ^| find ":%SOLR_PORT% "') do ( - IF NOT "%%N"=="0" ( - IF "%%M"=="%SOLR_JETTY_HOST%:%SOLR_PORT%" ( - set found_it=1 - @echo Stopping Solr process %%N running on port %SOLR_PORT% - IF "%STOP_PORT%"=="" set /A STOP_PORT=%SOLR_PORT% - 1000 - "%JAVA%" %SOLR_SSL_OPTS% %SOLR_TOOL_OPTS% -Djetty.home="%SOLR_SERVER_DIR%" -jar "%SOLR_SERVER_DIR%\start.jar" %SOLR_JETTY_CONFIG% STOP.PORT=!STOP_PORT! STOP.KEY=%STOP_KEY% --stop - del "%SOLR_TIP%"\bin\solr-%SOLR_PORT%.port - REM wait for the process to terminate - CALL :wait_for_process_exit %%N !SOLR_STOP_WAIT! - REM Kill it if it is still running after the graceful shutdown - IF EXIST "%JAVA_HOME%\bin\jstack.exe" ( - qprocess "%%N" >nul 2>nul && "%JAVA_HOME%\bin\jstack.exe" %%N && taskkill /f /PID %%N - ) else ( - qprocess "%%N" >nul 2>nul && taskkill /f /PID %%N - ) + set "SCRIPT_ERROR=Must specify the port when trying to stop Solr, or use --all to stop all running nodes on this host." + goto err + ) +) ELSE ( + REM Stop Solr running on specific port + set found_it=0 + For /f "tokens=2,5" %%M in ('netstat -nao ^| find "TCP " ^| find ":0 " ^| find ":%SOLR_PORT% "') do ( + IF NOT "%%N"=="0" ( + IF "%%M"=="%SOLR_JETTY_HOST%:%SOLR_PORT%" ( + set found_it=1 + @echo Stopping Solr process %%N running on port %SOLR_PORT% + IF "%STOP_PORT%"=="" set /A STOP_PORT=%SOLR_PORT% - 1000 + "%JAVA%" %SOLR_SSL_OPTS% %SOLR_TOOL_OPTS% -Djetty.home="%SOLR_SERVER_DIR%" -jar "%SOLR_SERVER_DIR%\start.jar" %SOLR_JETTY_CONFIG% STOP.PORT=!STOP_PORT! STOP.KEY=%STOP_KEY% --stop + del "%SOLR_TIP%"\bin\solr-%SOLR_PORT%.port + REM wait for the process to terminate + CALL :wait_for_process_exit %%N !SOLR_STOP_WAIT! + REM Kill it if it is still running after the graceful shutdown + IF EXIST "%JAVA_HOME%\bin\jstack.exe" ( + qprocess "%%N" >nul 2>nul && "%JAVA_HOME%\bin\jstack.exe" %%N && taskkill /f /PID %%N + ) else ( + qprocess "%%N" >nul 2>nul && taskkill /f /PID %%N ) ) ) - if "!found_it!"=="0" echo No Solr found running on port %SOLR_PORT% ) + if "!found_it!"=="0" echo No Solr found running on port %SOLR_PORT% +) + +IF "!IS_RESTART!"=="0" goto done - IF "!IS_RESTART!"=="0" goto done +REM Clean state here, continue with starting (start or restart) +set SCRIPT_CMD=start + +:start_solr +REM Prepare for starting Solr +IF "%SOLR_HOME%"=="" set "SOLR_HOME=%SOLR_SERVER_DIR%\solr" +IF EXIST "%cd%\%SOLR_HOME%" set "SOLR_HOME=%cd%\%SOLR_HOME%" + +IF NOT EXIST "%SOLR_HOME%\" ( + IF EXIST "%SOLR_SERVER_DIR%\%SOLR_HOME%" ( + set "SOLR_HOME=%SOLR_SERVER_DIR%\%SOLR_HOME%" + ) ELSE ( + set "SCRIPT_ERROR=Solr home directory %SOLR_HOME% not found!" + goto err + ) +) + +@REM This is quite hacky, but examples rely on a different log4j2.xml +@REM so that we can write logs for examples to %SOLR_HOME%\..\logs +IF [%SOLR_LOGS_DIR%] == [] ( + set "SOLR_LOGS_DIR=%SOLR_SERVER_DIR%\logs" +) ELSE ( + set SOLR_LOGS_DIR=%SOLR_LOGS_DIR:"=% +) + +set "EXAMPLE_DIR=%SOLR_TIP%\example" +set TMP_SOLR_HOME=!SOLR_HOME:%EXAMPLE_DIR%=! +IF NOT "%TMP_SOLR_HOME%"=="%SOLR_HOME%" ( + set "SOLR_LOGS_DIR=%SOLR_HOME%\..\logs" + set "LOG4J_CONFIG=%SOLR_SERVER_DIR%\resources\log4j2.xml" ) -IF "!IS_RESTART!"=="1" set SCRIPT_CMD=start IF "%SOLR_PORT%"=="" set SOLR_PORT=8983 IF "%STOP_PORT%"=="" set /A STOP_PORT=%SOLR_PORT% - 1000 @@ -862,21 +874,19 @@ IF DEFINED SOLR_ZK_EMBEDDED_HOST ( set "SCRIPT_SOLR_OPTS=%SCRIPT_SOLR_OPTS% -Dsolr.zk.embedded.host=%SOLR_ZK_EMBEDDED_HOST%" ) -IF "%SCRIPT_CMD%"=="start" ( - REM see if Solr is already running using netstat - For /f "tokens=2,5" %%j in ('netstat -aon ^| find "TCP " ^| find ":0 " ^| find ":%SOLR_PORT% "') do ( - IF NOT "%%k"=="0" ( - IF "%%j"=="%SOLR_JETTY_HOST%:%SOLR_PORT%" ( - set "SCRIPT_ERROR=Process %%k is already listening on port %SOLR_PORT%. If this is Solr, please stop it first before starting (or use restart). If this is not Solr, then please choose a different port using -p PORT" - goto err - ) +REM Make sure Solr is not running using netstat +For /f "tokens=2,5" %%j in ('netstat -aon ^| find "TCP " ^| find ":0 " ^| find ":%SOLR_PORT% "') do ( + IF NOT "%%k"=="0" ( + IF "%%j"=="%SOLR_JETTY_HOST%:%SOLR_PORT%" ( + set "SCRIPT_ERROR=Process %%k is already listening on port %SOLR_PORT%. If this is Solr, please stop it first before starting (or use restart). If this is not Solr, then please choose a different port using -p PORT" + goto err ) ) +) - IF "%EMPTY_ADDL_JVM_ARGS%"=="true" ( - set "SCRIPT_ERROR=JVM options are required when using the -a or --jvm-opts option!" - goto err - ) +IF "%EMPTY_ADDL_JVM_ARGS%"=="true" ( + set "SCRIPT_ERROR=JVM options are required when using the -a or --jvm-opts option!" + goto err ) @REM determine if -server flag is supported by current JVM @@ -890,21 +900,9 @@ IF ERRORLEVEL 1 ( set IS_JDK=true set "SERVEROPT=-server" ) -if !JAVA_MAJOR_VERSION! LSS 9 ( - "%JAVA%" -d64 -version > nul 2>&1 - IF ERRORLEVEL 1 ( - set "IS_64BIT=false" - @echo WARNING: 32-bit Java detected. Not recommended for production. Point your JAVA_HOME to a 64-bit JDK - @echo. - ) ELSE ( - set IS_64bit=true - ) -) ELSE ( - set IS_64bit=true -) IF NOT "%ZK_HOST%"=="" set SOLR_MODE=solrcloud -IF NOT "%SOLR_MODE%"=="" set SOLR_MODE=solrcloud +IF "%SOLR_MODE%"=="" set SOLR_MODE=solrcloud IF "%SOLR_MODE%"=="solrcloud" ( IF "%ZK_CLIENT_TIMEOUT%"=="" set "ZK_CLIENT_TIMEOUT=30000" @@ -941,7 +939,7 @@ IF "%SOLR_MODE%"=="solrcloud" ( IF EXIST "%SOLR_HOME%\collection1\core.properties" set "CLOUD_MODE_OPTS=!CLOUD_MODE_OPTS! -Dbootstrap_confdir=./solr/collection1/conf -Dcollection.configName=myconf -DnumShards=1" ) ELSE ( REM change Cloud mode to User Managed mode with flag - set "CLOUD_MODE_OPTS=--user-managed" + set "CLOUD_MODE_OPTS=" IF NOT EXIST "%SOLR_HOME%\solr.xml" ( IF "%SOLR_SOLRXML_REQUIRED%"=="true" ( set "SCRIPT_ERROR=Solr home directory %SOLR_HOME% must contain solr.xml!" @@ -1015,41 +1013,11 @@ IF "%GC_TUNE%"=="" ( -XX:+ExplicitGCInvokesConcurrent ) -REM Workaround for JIT crash, see https://issues.apache.org/jira/browse/SOLR-16463 -if !JAVA_MAJOR_VERSION! GEQ 17 ( - set SCRIPT_SOLR_OPTS=%SCRIPT_SOLR_OPTS% -XX:CompileCommand=exclude,com.github.benmanes.caffeine.cache.BoundedLocalCache::put - echo Java %JAVA_MAJOR_VERSION% detected. Enabled workaround for SOLR-16463 -) - -REM Vector optimizations are only supported for Java 20 and 21 for now. -REM This will need to change as Lucene is upgraded and newer Java versions are released -if !JAVA_MAJOR_VERSION! GEQ 20 if !JAVA_MAJOR_VERSION! LEQ 21 ( - set SCRIPT_SOLR_OPTS=%SCRIPT_SOLR_OPTS% --add-modules jdk.incubator.vector - echo Java %JAVA_MAJOR_VERSION% detected. Incubating Panama Vector APIs have been enabled -) +REM Add vector optimizations module +set SCRIPT_SOLR_OPTS=%SCRIPT_SOLR_OPTS% --add-modules jdk.incubator.vector -if !JAVA_MAJOR_VERSION! GEQ 9 if NOT "%JAVA_VENDOR%" == "OpenJ9" ( - IF NOT "%GC_LOG_OPTS%"=="" ( - echo ERROR: On Java 9 you cannot set GC_LOG_OPTS, only default GC logging is available. Exiting - GOTO :eof - ) - set GC_LOG_OPTS="-Xlog:gc*:file=\"!SOLR_LOGS_DIR!\solr_gc.log\":time,uptime:filecount=9,filesize=20M" -) else ( - IF "%GC_LOG_OPTS%"=="" ( - rem Set defaults for Java 8 - set GC_LOG_OPTS=-verbose:gc ^ - -XX:+PrintHeapAtGC ^ - -XX:+PrintGCDetails ^ - -XX:+PrintGCDateStamps ^ - -XX:+PrintGCTimeStamps ^ - -XX:+PrintTenuringDistribution ^ - -XX:+PrintGCApplicationStoppedTime - ) - if "%JAVA_VENDOR%" == "OpenJ9" ( - set GC_LOG_OPTS=!GC_LOG_OPTS! "-Xverbosegclog:!SOLR_LOGS_DIR!\solr_gc.log" -XX:+UseGCLogFileRotation -XX:NumberOfGCLogFiles=9 -XX:GCLogFileSize=20M - ) else ( - set GC_LOG_OPTS=!GC_LOG_OPTS! "-Xloggc:!SOLR_LOGS_DIR!\solr_gc.log" -XX:+UseGCLogFileRotation -XX:NumberOfGCLogFiles=9 -XX:GCLogFileSize=20M - ) +IF "%GC_LOG_OPTS%"=="" ( + set GC_LOG_OPTS="-Xlog:gc*" ) IF "%verbose%"=="1" ( @@ -1127,7 +1095,7 @@ IF "%SOLR_SSL_ENABLED%"=="true" ( set SOLR_LOGS_DIR_QUOTED="%SOLR_LOGS_DIR%" set SOLR_DATA_HOME_QUOTED="%SOLR_DATA_HOME%" -set "START_OPTS=%START_OPTS% -Dsolr.log.dir=%SOLR_LOGS_DIR_QUOTED% -Djava.util.logging.manager=org.apache.logging.log4j.jul.LogManager" +set "START_OPTS=%START_OPTS% -Dsolr.log.dir=%SOLR_LOGS_DIR_QUOTED%" IF NOT "%SOLR_DATA_HOME%"=="" set "START_OPTS=%START_OPTS% -Dsolr.data.home=%SOLR_DATA_HOME_QUOTED%" IF NOT DEFINED LOG4J_CONFIG set "LOG4J_CONFIG=%SOLR_SERVER_DIR%\resources\log4j2.xml" @@ -1178,9 +1146,8 @@ IF "%FG%"=="1" ( -Djava.io.tmpdir="%SOLR_SERVER_DIR%\tmp" -jar start.jar %SOLR_JETTY_CONFIG% "%SOLR_JETTY_ADDL_CONFIG%" > "!SOLR_LOGS_DIR!\solr-%SOLR_PORT%-console.log" echo %SOLR_PORT%>"%SOLR_TIP%"\bin\solr-%SOLR_PORT%.port - REM default to 30 seconds for backwards compatibility. IF "!SOLR_START_WAIT!"=="" ( - set SOLR_START_WAIT=30 + set SOLR_START_WAIT=180 ) REM now wait to see Solr come online ... "%JAVA%" %SOLR_SSL_OPTS% %AUTHC_OPTS% %SOLR_ZK_CREDS_AND_ACLS% %SOLR_TOOL_OPTS% -Dsolr.install.dir="%SOLR_TIP%" -Dsolr.default.confdir="%DEFAULT_CONFDIR%"^ @@ -1195,319 +1162,7 @@ IF "%FG%"=="1" ( goto done -:run_example -REM Run the requested example - -"%JAVA%" %SOLR_SSL_OPTS% %AUTHC_OPTS% %SOLR_ZK_CREDS_AND_ACLS% %SOLR_TOOL_OPTS% -Dsolr.install.dir="%SOLR_TIP%" ^ - -Dlog4j.configurationFile="file:///%DEFAULT_SERVER_DIR%\resources\log4j2-console.xml" ^ - -Dsolr.install.symDir="%SOLR_TIP%" ^ - -classpath "%DEFAULT_SERVER_DIR%\solr-webapp\webapp\WEB-INF\lib\*;%DEFAULT_SERVER_DIR%\lib\ext\*" ^ - org.apache.solr.cli.SolrCLI run_example --script "%SDIR%\solr.cmd" -e %EXAMPLE% --server-dir "%SOLR_SERVER_DIR%" ^ - --url-scheme !SOLR_URL_SCHEME! !PASS_TO_RUN_EXAMPLE! - -REM End of run_example -goto done - -:get_status -REM Find all Java processes, correlate with those listening on a port -REM and then try to contact via that port using the status tool -for /f "usebackq" %%i in (`dir /b "%SOLR_TIP%\bin" ^| findstr /i "^solr-.*\.port$"`) do ( - set SOME_SOLR_PORT= - For /F "Delims=" %%J In ('type "%SOLR_TIP%\bin\%%i"') do set SOME_SOLR_PORT=%%~J - if NOT "!SOME_SOLR_PORT!"=="" ( - for /f "tokens=2,5" %%j in ('netstat -aon ^| find "TCP " ^| find ":0 " ^| find ":!SOME_SOLR_PORT! "') do ( - IF NOT "%%k"=="0" ( - if "%%j"=="%SOLR_JETTY_HOST%:!SOME_SOLR_PORT!" ( - @echo. - set has_info=1 - echo Found Solr process %%k running on port !SOME_SOLR_PORT! - REM Passing in %2 (-h or --help) directly is captured by a custom help path for usage output - "%JAVA%" %SOLR_SSL_OPTS% %AUTHC_OPTS% %SOLR_ZK_CREDS_AND_ACLS% %SOLR_TOOL_OPTS% -Dsolr.install.dir="%SOLR_TIP%" ^ - -Dlog4j.configurationFile="file:///%DEFAULT_SERVER_DIR%\resources\log4j2-console.xml" ^ - -classpath "%DEFAULT_SERVER_DIR%\solr-webapp\webapp\WEB-INF\lib\*;%DEFAULT_SERVER_DIR%\lib\ext\*" ^ - org.apache.solr.cli.SolrCLI status --solr-url !SOLR_URL_SCHEME!://%SOLR_TOOL_HOST%:!SOME_SOLR_PORT! %2 - @echo. - ) - ) - ) - ) -) -if NOT "!has_info!"=="1" echo No running Solr nodes found. -set has_info= -goto done - -:run_solrcli -"%JAVA%" %SOLR_SSL_OPTS% %AUTHC_OPTS% %SOLR_ZK_CREDS_AND_ACLS% %SOLR_TOOL_OPTS% -Dsolr.install.dir="%SOLR_TIP%" ^ - -Dlog4j.configurationFile="file:///%DEFAULT_SERVER_DIR%\resources\log4j2-console.xml" ^ - -classpath "%DEFAULT_SERVER_DIR%\solr-webapp\webapp\WEB-INF\lib\*;%DEFAULT_SERVER_DIR%\lib\ext\*" ^ - org.apache.solr.cli.SolrCLI %* -if errorlevel 1 ( - exit /b 1 -) -goto done - -:parse_config_args -IF [%1]==[] goto run_config -IF "%1"=="-z" goto set_config_zk -IF "%1"=="--zk-host" goto set_config_zk -IF "%1"=="-zkHost" goto set_config_zk -IF "%1"=="--zkHost" goto set_config_zk -IF "%1"=="-s" goto set_config_url_scheme -IF "%1"=="-scheme" goto set_config_url_scheme -set "CONFIG_ARGS=!CONFIG_ARGS! %1" -SHIFT -goto parse_config_args - -:set_config_zk -set ZK_HOST=%~2 -SHIFT -SHIFT -goto parse_config_args - -:set_config_url_scheme -set SOLR_URL_SCHEME=%~2 -SHIFT -SHIFT -goto parse_config_args - -REM Clumsy to do the state machine thing for -d and -n, but that's required for back-compat -:parse_zk_args -IF "%1"=="-V" ( - goto set_zk_verbose -) ELSE IF "%1"=="upconfig" ( - goto set_zk_op -) ELSE IF "%1"=="downconfig" ( - goto set_zk_op -) ELSE IF "%1"=="cp" ( - goto set_zk_op -) ELSE IF "%1"=="mv" ( - goto set_zk_op -) ELSE IF "%1"=="rm" ( - goto set_zk_op -) ELSE IF "%1"=="ls" ( - goto set_zk_op -) ELSE IF "%1"=="mkroot" ( - goto set_zk_op -) ELSE IF "%1"=="linkconfig" ( - goto set_zk_op -) ELSE IF "%1"=="updateacls" ( - goto set_zk_op -) ELSE IF "%1"=="-n" ( - goto set_config_name -) ELSE IF "%1"=="-r" ( - goto set_zk_recursive -) ELSE IF "%1"=="-configname" ( - goto set_config_name -) ELSE IF "%1"=="-d" ( - goto set_configdir -) ELSE IF "%1"=="-confdir" ( - goto set_configdir -) ELSE IF "%1"=="--conf-dir" ( - goto set_configdir -) ELSE IF "%1"=="-c" ( - goto set_collection_zk -) ELSE IF "%1"=="-z" ( - goto set_config_zk -) ELSE IF "!ZK_SRC!"=="" ( - if not "%~1"=="" ( - goto set_zk_src - ) -) ELSE IF "!ZK_DST!"=="" ( - IF "%ZK_OP%"=="cp" ( - goto set_zk_dst - ) - IF "%ZK_OP%"=="mv" ( - goto set_zk_dst - ) - set ZK_DST="_" -) ELSE IF NOT "%1"=="" ( - set ERROR_MSG="Unrecognized or misplaced zk argument %1%" - goto zk_short_usage -) -goto run_zk - -:set_zk_op -set ZK_OP=%~1 -SHIFT -goto parse_zk_args - -:set_zk_verbose -set ZK_VERBOSE="--verbose" -SHIFT -goto parse_zk_args - -:set_config_name -set CONFIGSET_NAME=%~2 -SHIFT -SHIFT -goto parse_zk_args - -:set_configdir -set CONFIGSET_DIR=%~2 -SHIFT -SHIFT -goto parse_zk_args - -:set_collection_zk -set ZK_COLLECTION=%~2 -SHIFT -SHIFT -goto parse_zk_args - -:set_config_zk -set ZK_HOST=%~2 -SHIFT -SHIFT -goto parse_zk_args - -:set_zk_src -set ZK_SRC=%~1 -SHIFT -goto parse_zk_args - -:set_zk_dst -set ZK_DST=%~1 -SHIFT -goto parse_zk_args - -:set_zk_recursive -set ZK_RECURSIVE="true" -SHIFT -goto parse_zk_args - -:run_zk -IF "!ZK_OP!"=="" ( - set "ERROR_MSG=Invalid command specified for zk sub-command" - goto zk_short_usage -) - -set CONNECTION_PARAMS="" - -IF "!ZK_OP!"=="" ( - set CONNECTION_PARAMS="--solr-url !ZK_SOLR_URL!" -) -ELSE ( - set CONNECTION_PARAMS="--zk-host ZK_HOST!" -) - -IF "!ZK_OP!"=="upconfig" ( - IF "!CONFIGSET_NAME!"=="" ( - set ERROR_MSG="-n option must be set for upconfig" - goto zk_short_usage - ) - IF "!CONFIGSET_DIR!"=="" ( - set ERROR_MSG="The -d option must be set for upconfig." - goto zk_short_usage - ) - "%JAVA%" %SOLR_SSL_OPTS% %AUTHC_OPTS% %SOLR_ZK_CREDS_AND_ACLS% %SOLR_TOOL_OPTS% -Dsolr.install.dir="%SOLR_TIP%" ^ - -Dlog4j.configurationFile="file:///%DEFAULT_SERVER_DIR%\resources\log4j2-console.xml" ^ - -classpath "%DEFAULT_SERVER_DIR%\solr-webapp\webapp\WEB-INF\lib\*;%DEFAULT_SERVER_DIR%\lib\ext\*" ^ - org.apache.solr.cli.SolrCLI !ZK_OP! --conf-name !CONFIGSET_NAME! --conf-dir !CONFIGSET_DIR! %CONNECTION_PARAMS% %ZK_VERBOSE%^ -) ELSE IF "!ZK_OP!"=="downconfig" ( - IF "!CONFIGSET_NAME!"=="" ( - set ERROR_MSG="-n option must be set for downconfig" - goto zk_short_usage - ) - IF "!CONFIGSET_DIR!"=="" ( - set ERROR_MSG="The -d option must be set for downconfig." - goto zk_short_usage - ) - "%JAVA%" %SOLR_SSL_OPTS% %AUTHC_OPTS% %SOLR_ZK_CREDS_AND_ACLS% %SOLR_TOOL_OPTS% -Dsolr.install.dir="%SOLR_TIP%" ^ - -Dlog4j.configurationFile="file:///%DEFAULT_SERVER_DIR%\resources\log4j2-console.xml" ^ - -classpath "%DEFAULT_SERVER_DIR%\solr-webapp\webapp\WEB-INF\lib\*;%DEFAULT_SERVER_DIR%\lib\ext\*" ^ - org.apache.solr.cli.SolrCLI !ZK_OP! --conf-name !CONFIGSET_NAME! --conf-dir !CONFIGSET_DIR! -z !ZK_HOST! %ZK_VERBOSE% -) ELSE IF "!ZK_OP!"=="linkconfig" ( - IF "!CONFIGSET_NAME!"=="" ( - set ERROR_MSG="-n option must be set for linkconfig" - goto zk_short_usage - ) - IF "!ZK_COLLECTION!"=="" ( - set ERROR_MSG="The -c option must be set for linkconfig." - goto zk_short_usage - ) - "%JAVA%" %SOLR_SSL_OPTS% %AUTHC_OPTS% %SOLR_ZK_CREDS_AND_ACLS% %SOLR_TOOL_OPTS% -Dsolr.install.dir="%SOLR_TIP%" ^ - -Dlog4j.configurationFile="file:///%DEFAULT_SERVER_DIR%\resources\log4j2-console.xml" ^ - -classpath "%DEFAULT_SERVER_DIR%\solr-webapp\webapp\WEB-INF\lib\*;%DEFAULT_SERVER_DIR%\lib\ext\*" ^ - org.apache.solr.cli.SolrCLI !ZK_OP! --conf-name !CONFIGSET_NAME! -c !ZK_COLLECTION! -z !ZK_HOST! %ZK_VERBOSE% -) ELSE IF "!ZK_OP!"=="updateacls" ( - IF "%ZK_SRC"=="" ( - set ERROR_MSG="Zookeeper path to remove must be specified when using the 'ls' command" - goto zk_short_usage - ) - "%JAVA%" %SOLR_SSL_OPTS% %AUTHC_OPTS% %SOLR_ZK_CREDS_AND_ACLS% %SOLR_TOOL_OPTS% -Dsolr.install.dir="%SOLR_TIP%" ^ - -Dlog4j.configurationFile="file:///%DEFAULT_SERVER_DIR%\resources\log4j2-console.xml" ^ - -classpath "%DEFAULT_SERVER_DIR%\solr-webapp\webapp\WEB-INF\lib\*;%DEFAULT_SERVER_DIR%\lib\ext\*" ^ - org.apache.solr.cli.SolrCLI !ZK_OP! --path !ZK_SRC! -z !ZK_HOST! %ZK_VERBOSE% -) ELSE IF "!ZK_OP!"=="cp" ( - IF "%ZK_SRC%"=="" ( - set ERROR_MSG=" must be specified for 'cp' command" - goto zk_short_usage - ) - IF "%ZK_DST%"=="" ( - set ERROR_MSG= must be specified for 'cp' command" - goto zk_short_usage - ) - IF NOT "!ZK_SRC:~0,3!"=="zk:" ( - IF NOT "!%ZK_DST:~0,3!"=="zk:" ( - set ERROR_MSG="At least one of src or dst must be prefixed by 'zk:'" - goto zk_short_usage - ) - ) - "%JAVA%" %SOLR_SSL_OPTS% %AUTHC_OPTS% %SOLR_ZK_CREDS_AND_ACLS% %SOLR_TOOL_OPTS% -Dsolr.install.dir="%SOLR_TIP%" ^ - -Dlog4j.configurationFile="file:///%DEFAULT_SERVER_DIR%\resources\log4j2-console.xml" ^ - -classpath "%DEFAULT_SERVER_DIR%\solr-webapp\webapp\WEB-INF\lib\*;%DEFAULT_SERVER_DIR%\lib\ext\*" ^ - org.apache.solr.cli.SolrCLI !ZK_OP! -z !ZK_HOST! --source !ZK_SRC! --destination !ZK_DST! --recursive !ZK_RECURSIVE! %ZK_VERBOSE% -) ELSE IF "!ZK_OP!"=="mv" ( - IF "%ZK_SRC%"=="" ( - set ERROR_MSG=" must be specified for 'mv' command" - goto zk_short_usage - ) - IF "%ZK_DST%"=="" ( - set ERROR_MSG=" must be specified for 'mv' command" - goto zk_short_usage - ) - "%JAVA%" %SOLR_SSL_OPTS% %AUTHC_OPTS% %SOLR_ZK_CREDS_AND_ACLS% %SOLR_TOOL_OPTS% -Dsolr.install.dir="%SOLR_TIP%" ^ - -Dlog4j.configurationFile="file:///%DEFAULT_SERVER_DIR%\resources\log4j2-console.xml" ^ - -classpath "%DEFAULT_SERVER_DIR%\solr-webapp\webapp\WEB-INF\lib\*;%DEFAULT_SERVER_DIR%\lib\ext\*" ^ - org.apache.solr.cli.SolrCLI !ZK_OP! -z !ZK_HOST! --source !ZK_SRC! --destination !ZK_DST! %ZK_VERBOSE% -) ELSE IF "!ZK_OP!"=="rm" ( - IF "%ZK_SRC"=="" ( - set ERROR_MSG="Zookeeper path to remove must be specified when using the 'rm' command" - goto zk_short_usage - ) - "%JAVA%" %SOLR_SSL_OPTS% %AUTHC_OPTS% %SOLR_ZK_CREDS_AND_ACLS% %SOLR_TOOL_OPTS% -Dsolr.install.dir="%SOLR_TIP%" ^ - -Dlog4j.configurationFile="file:///%DEFAULT_SERVER_DIR%\resources\log4j2-console.xml" ^ - -classpath "%DEFAULT_SERVER_DIR%\solr-webapp\webapp\WEB-INF\lib\*;%DEFAULT_SERVER_DIR%\lib\ext\*" ^ - org.apache.solr.cli.SolrCLI !ZK_OP! -z !ZK_HOST! --path !ZK_SRC! --recursive !ZK_RECURSIVE! %ZK_VERBOSE% -) ELSE IF "!ZK_OP!"=="ls" ( - IF "%ZK_SRC"=="" ( - set ERROR_MSG="Zookeeper path to remove must be specified when using the 'ls' command" - goto zk_short_usage - ) - "%JAVA%" %SOLR_SSL_OPTS% %AUTHC_OPTS% %SOLR_ZK_CREDS_AND_ACLS% %SOLR_TOOL_OPTS% -Dsolr.install.dir="%SOLR_TIP%" ^ - -Dlog4j.configurationFile="file:///%DEFAULT_SERVER_DIR%\resources\log4j2-console.xml" ^ - -classpath "%DEFAULT_SERVER_DIR%\solr-webapp\webapp\WEB-INF\lib\*;%DEFAULT_SERVER_DIR%\lib\ext\*" ^ - org.apache.solr.cli.SolrCLI !ZK_OP! -z !ZK_HOST! --path !ZK_SRC! --recursive !ZK_RECURSIVE! %ZK_VERBOSE% -) ELSE IF "!ZK_OP!"=="mkroot" ( - IF "%ZK_SRC"=="" ( - set ERROR_MSG="Zookeeper path to create must be specified when using the 'mkroot' command" - goto zk_short_usage - ) - "%JAVA%" %SOLR_SSL_OPTS% %AUTHC_OPTS% %SOLR_ZK_CREDS_AND_ACLS% %SOLR_TOOL_OPTS% -Dsolr.install.dir="%SOLR_TIP%" ^ - -Dlog4j.configurationFile="file:///%SOLR_SERVER_DIR%\resources\log4j2-console.xml" ^ - -classpath "%DEFAULT_SERVER_DIR%\solr-webapp\webapp\WEB-INF\lib\*;%DEFAULT_SERVER_DIR%\lib\ext\*" ^ - org.apache.solr.cli.SolrCLI !ZK_OP! -z !ZK_HOST! --path !ZK_SRC! %ZK_VERBOSE% -) ELSE ( - set ERROR_MSG="Unknown zk option !ZK_OP!" - goto zk_short_usage -) -goto done - - :run_auth -IF "%1"=="-help" goto usage -IF "%1"=="-usage" goto usage - REM Options parsing. REM Note: With the following technique of parsing, it is not possible REM to have an option without a value. @@ -1519,11 +1174,11 @@ for %%a in (%*) do ( if "!arg:~0,1!" equ "-" set "option=!arg!" ) else ( set "option!option!=%%a" - if "!option!" equ "-d" set "SOLR_SERVER_DIR=%%a" - if "!option!" equ "--server-dir" set "SOLR_SERVER_DIR=%%a" if "!option!" equ "-s" set "SOLR_HOME=%%a" - if "!option!" equ "--solr-home" set "SOLR_HOME=%%a" - if not "!option!" equ "-s" if not "!option!" equ "-d" ( + if "!option!" equ "--solr-home" set "SOLR_HOME=%%a" + if "!option!" equ "-d" set "SOLR_SERVER_DIR=%%a" + if "!option!" equ "--server-dir" set "SOLR_SERVER_DIR=%%a" + if not "!option!" equ "-s" if not "!option!" equ "--solr-home" if not "!option!" equ "-d" if not "!option!" equ "--server-dir" ( set "AUTH_PARAMS=!AUTH_PARAMS! !option! %%a" ) set "option=" @@ -1563,53 +1218,12 @@ if "!AUTH_PORT!"=="" ( --solr-url !SOLR_URL_SCHEME!://%SOLR_TOOL_HOST%:!AUTH_PORT! goto done - -:invalid_cmd_line -@echo. -IF "!SCRIPT_ERROR!"=="" ( - @echo Invalid command-line option: %1 -) ELSE ( - @echo ERROR: !SCRIPT_ERROR! -) -@echo. -IF "%FIRST_ARG%"=="start" ( - goto start_usage -) ELSE IF "%FIRST_ARG:~0,1%" == "-" ( - goto start_usage -) ELSE IF "%FIRST_ARG%"=="restart" ( - goto start_usage -) ELSE IF "%FIRST_ARG%"=="stop" ( - goto stop_usage -) ELSE IF "%FIRST_ARG%"=="healthcheck" ( - goto run_solrcli -) ELSE IF "%FIRST_ARG%"=="create" ( - goto run_solrcli -) ELSE IF "%FIRST_ARG%"=="zk" ( - goto zk_short_usage -) ELSE IF "%FIRST_ARG%"=="auth" ( - goto auth_usage -) ELSE IF "%FIRST_ARG%"=="status" ( - goto run_solrcli -) - -:need_java_home -@echo Please set the JAVA_HOME environment variable to the path where you installed Java 1.8+ -goto done - -:need_java_vers -@echo Java 1.8 or later is required to run Solr. -goto done - :err @echo. @echo ERROR: !SCRIPT_ERROR! @echo. exit /b 1 -:done -ENDLOCAL -exit /b 0 - REM Tests what Java we have and sets some global variables :resolve_java_info @@ -1683,3 +1297,7 @@ GOTO :eof ) ) GOTO :eof + +:done +ENDLOCAL +exit /b 0 diff --git a/solr/bin/solr.in.cmd b/solr/bin/solr.in.cmd index 77b1117208a..ac058eae131 100755 --- a/solr/bin/solr.in.cmd +++ b/solr/bin/solr.in.cmd @@ -49,15 +49,8 @@ REM set GC_TUNE=-XX:+ExplicitGCInvokesConcurrent REM set GC_TUNE=-XX:SurvivorRatio=4 REM set GC_TUNE=%GC_TUNE% -XX:TargetSurvivorRatio=90 REM set GC_TUNE=%GC_TUNE% -XX:MaxTenuringThreshold=8 -REM set GC_TUNE=%GC_TUNE% -XX:+UseConcMarkSweepGC -REM set GC_TUNE=%GC_TUNE% -XX:ConcGCThreads=4 REM set GC_TUNE=%GC_TUNE% -XX:ParallelGCThreads=4 -REM set GC_TUNE=%GC_TUNE% -XX:+CMSScavengeBeforeRemark REM set GC_TUNE=%GC_TUNE% -XX:PretenureSizeThreshold=64m -REM set GC_TUNE=%GC_TUNE% -XX:+UseCMSInitiatingOccupancyOnly -REM set GC_TUNE=%GC_TUNE% -XX:CMSInitiatingOccupancyFraction=50 -REM set GC_TUNE=%GC_TUNE% -XX:CMSMaxAbortablePrecleanTime=6000 -REM set GC_TUNE=%GC_TUNE% -XX:+CMSParallelRemarkEnabled REM set GC_TUNE=%GC_TUNE% -XX:+ParallelRefProcEnabled etc. REM Set the ZooKeeper connection string if using an external ZooKeeper ensemble @@ -97,7 +90,7 @@ REM set RMI_PORT=18983 REM Anything you add to the SOLR_OPTS variable will be included in the java REM start command line as-is, in ADDITION to other options. If you specify the -REM -a option on start script, those options will be appended as well. Examples: +REM --jvm-opts option on start script, those options will be appended as well. Examples: REM set SOLR_OPTS=%SOLR_OPTS% -Dsolr.autoSoftCommit.maxTime=3000 REM set SOLR_OPTS=%SOLR_OPTS% -Dsolr.autoCommit.maxTime=60000 @@ -262,4 +255,4 @@ REM set SOLR_MODULES=extraction,ltr REM Configure the default replica placement plugin to use if one is not configured in cluster properties REM See https://solr.apache.org/guide/solr/latest/configuration-guide/replica-placement-plugins.html for details -REM set SOLR_PLACEMENTPLUGIN_DEFAULT=simple \ No newline at end of file +REM set SOLR_PLACEMENTPLUGIN_DEFAULT=simple diff --git a/solr/bin/solr.in.sh b/solr/bin/solr.in.sh index 4202b98cd68..9d83a48c1c2 100644 --- a/solr/bin/solr.in.sh +++ b/solr/bin/solr.in.sh @@ -55,14 +55,8 @@ #-XX:SurvivorRatio=4 \ #-XX:TargetSurvivorRatio=90 \ #-XX:MaxTenuringThreshold=8 \ -#-XX:+UseConcMarkSweepGC \ -#-XX:ConcGCThreads=4 -XX:ParallelGCThreads=4 \ -#-XX:+CMSScavengeBeforeRemark \ +#-XX:ParallelGCThreads=4 \ #-XX:PretenureSizeThreshold=64m \ -#-XX:+UseCMSInitiatingOccupancyOnly \ -#-XX:CMSInitiatingOccupancyFraction=50 \ -#-XX:CMSMaxAbortablePrecleanTime=6000 \ -#-XX:+CMSParallelRemarkEnabled \ #-XX:+ParallelRefProcEnabled etc. # Set the ZooKeeper connection string if using an external ZooKeeper ensemble @@ -279,7 +273,7 @@ # other directory, which will implicitly enable heap dumping. Dump name pattern will be solr-[timestamp]-pid[###].hprof # When using this feature, it is recommended to have an external service monitoring the given dir. # If more fine grained control is required, you can manually add the appropriate flags to SOLR_OPTS -# See https://docs.oracle.com/en/java/javase/11/troubleshoot/command-line-options1.html +# See https://docs.oracle.com/en/java/javase/21/troubleshoot/command-line-options1.html # You can test this behavior by setting SOLR_HEAP=25m #SOLR_HEAP_DUMP=true #SOLR_HEAP_DUMP_DIR=/var/log/dumps diff --git a/solr/core/build.gradle b/solr/core/build.gradle index b36843fa568..92bbfbe1120 100644 --- a/solr/core/build.gradle +++ b/solr/core/build.gradle @@ -49,7 +49,6 @@ dependencies { api project(':solr:solrj-zookeeper') api project(':solr:solrj-streaming') - api 'io.dropwizard.metrics:metrics-core' implementation ('io.dropwizard.metrics:metrics-graphite', { exclude group: "com.rabbitmq", module: "amqp-client" @@ -125,6 +124,16 @@ dependencies { implementation 'org.eclipse.jetty.toolchain:jetty-servlet-api' // ZooKeeper + + implementation('org.apache.curator:curator-framework', { + exclude group: 'org.apache.zookeeper', module: 'zookeeper' + }) + implementation('org.apache.curator:curator-client', { + exclude group: 'org.apache.zookeeper', module: 'zookeeper' + }) + testImplementation('org.apache.curator:curator-test', { + exclude group: 'org.apache.zookeeper', module: 'zookeeper' + }) implementation('org.apache.zookeeper:zookeeper', { exclude group: "org.apache.yetus", module: "audience-annotations" }) diff --git a/solr/core/src/java/org/apache/solr/cli/ApiTool.java b/solr/core/src/java/org/apache/solr/cli/ApiTool.java index 76c6aa6f60f..02f893b3753 100644 --- a/solr/core/src/java/org/apache/solr/cli/ApiTool.java +++ b/solr/core/src/java/org/apache/solr/cli/ApiTool.java @@ -19,10 +19,9 @@ import java.io.PrintStream; import java.net.URI; -import java.util.List; import org.apache.commons.cli.CommandLine; -import org.apache.commons.cli.DeprecatedAttributes; import org.apache.commons.cli.Option; +import org.apache.commons.cli.Options; import org.apache.solr.client.solrj.SolrRequest; import org.apache.solr.client.solrj.impl.JsonMapResponseParser; import org.apache.solr.client.solrj.request.GenericSolrRequest; @@ -37,6 +36,16 @@ *

Used to send an arbitrary HTTP request to a Solr API endpoint. */ public class ApiTool extends ToolBase { + + private static final Option SOLR_URL_OPTION = + Option.builder("s") + .longOpt("solr-url") + .hasArg() + .argName("URL") + .required() + .desc("Send a GET request to a Solr API endpoint.") + .build(); + public ApiTool() { this(CLIO.getOutStream()); } @@ -51,43 +60,19 @@ public String getName() { } @Override - public List