All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.dspace.app.util.IndexVersion Maven / Gradle / Ivy

There is a newer version: 8.0
Show newest version
/**
 * The contents of this file are subject to the license and copyright
 * detailed in the LICENSE and NOTICE files at the root of the source
 * tree and available online at
 *
 * http://www.dspace.org/license/
 */
package org.dspace.app.util;

import java.io.File;
import java.io.IOException;
import java.text.ParseException;

import org.apache.lucene.index.SegmentCommitInfo;
import org.apache.lucene.index.SegmentInfos;
import org.apache.lucene.store.Directory;
import org.apache.lucene.store.FSDirectory;
import org.apache.lucene.util.Version;

/**
 * This utility class simply determines the version of a given Solr/Lucene index,
 * so that they can be upgraded to the latest version.
 * 

* You must pass it the full path of the index directory, e.g. * {@code [dspace]/solr/statistics/data/index/} *

* The response is simply a version number (e.g. 4.4), as this is utilized by * the {@code ant update_solr_indexes} target in {@code [src]/dspace/src/main/config/build.xml} * * @author tdonohue */ public class IndexVersion { /** * Default constructor */ private IndexVersion() { } public static void main(String[] argv) throws IOException { // Usage checks if (argv.length < 1) { System.out.println("\nRequired Solr/Lucene index directory is missing."); System.out.println("Minimally, pass in the full path of the Solr/Lucene Index directory to analyze"); System.out.println("Usage: IndexVersion [full-path-to-solr-index] ([version-to-compare])"); System.out.println(" - [full-path-to-index] is REQUIRED (e.g. [dspace.dir]/solr/statistics/data/index/)"); System.out.println(" - [version-to-compare] is optional. When specified, this command will return:"); System.out.println(" -1 if index dir version < version-to-compare"); System.out.println(" 0 if index dir version = version-to-compare"); System.out.println(" 1 if index dir version > version-to-compare"); System.out .println("\nOptionally, passing just '-v' will return the version of Solr/Lucene in use by DSpace."); System.exit(1); } // If "-v" passed on commandline, just return the current version of Solr/Lucene if (argv[0].equalsIgnoreCase("-v")) { System.out.println(getLatestVersion()); System.exit(0); } // First argument is the Index path. Determine its version String indexVersion = getIndexVersion(argv[0]); // Second argumet is an optional version number to compare to String compareToVersion = argv.length > 1 ? argv[1] : null; // If indexVersion comes back as null, then it is not a valid index directory. // So, exit immediately. if (indexVersion == null) { System.out.println("\nRequired Solr/Lucene index directory is invalid."); System.out.println("The following path does NOT seem to be a valid index directory:"); System.out.println(argv[0]); System.out.println("Please pass in the full path of the Solr/Lucene Index directory to analyze"); System.out.println("(e.g. [dspace.dir]/solr/statistics/data/index/)\n"); System.exit(1); } // If empty string is returned as the indexVersion, this means it's an // empty index directory. So, it's technically "compatible" with any version of Lucene. if (indexVersion.equals("")) { indexVersion = getLatestVersion(); } // If a compare-to-version was passed in, print the result of this comparison if (compareToVersion != null && !compareToVersion.isEmpty()) { // If the string "LATEST" is passed, determine which version of Lucene API we are using. if (compareToVersion.equalsIgnoreCase("LATEST")) { compareToVersion = getLatestVersion(); } System.out.println(compareSoftwareVersions(indexVersion, compareToVersion)); } else { // Otherwise, we'll just print the version of this index directory System.out.println(indexVersion); } System.exit(0); } /** * Determine the version of Solr/Lucene which was used to create a given index directory. * * @param indexDirPath Full path of the Solr/Lucene index directory * @return version as a string (e.g. "4.4"), empty string ("") if index directory is empty, * or null if directory doesn't exist. * @throws IOException if IO error */ public static String getIndexVersion(String indexDirPath) throws IOException { String indexVersion = null; // Make sure this directory exists File dir = new File(indexDirPath); if (dir.exists() && dir.isDirectory()) { // Check if this index directory has any contents String[] dirContents = dir.list(); // If this directory is empty, return an empty string. // It is a valid directory, but it's an empty index. if (dirContents != null && dirContents.length == 0) { return ""; } // Open this index directory in Lucene Directory indexDir = FSDirectory.open(dir.toPath()); // Get info on the Lucene segment file(s) in index directory SegmentInfos sis; try { sis = SegmentInfos.readLatestCommit(indexDir); } catch (IOException ie) { // Wrap default IOException, providing more info about which directory cannot be read throw new IOException("Could not read Lucene segments files in " + dir.getAbsolutePath(), ie); } if (null == sis) { throw new IOException("Could not read Lucene segments files in " + dir.getAbsolutePath()); } // If we have a valid Solr index dir, but it has no existing segments // then just return an empty string. It's a valid but empty index. if (sis.size() == 0) { return ""; } // Loop through our Lucene segment files to locate the OLDEST // version. It is possible for individual segment files to be // created by different versions of Lucene. So, we just need // to find the oldest version of Lucene which created these // index segment files. // This logic borrowed from Lucene v.4.10 CheckIndex class: // https://github.com/apache/lucene-solr/blob/lucene_solr_4_10/lucene/core/src/java/org/apache/lucene // /index/CheckIndex.java#L426 // WARNING: It MAY require updating whenever we upgrade the // "lucene.version" in our DSpace Parent POM Version oldest = null; Version oldSegment = null; for (SegmentCommitInfo si : sis) { // Get the version of Lucene which created this segment file Version version = si.info.getVersion(); if (version == null) { // If null, then this is a pre-3.1 segment file. // For our purposes, we will just assume it is "3.0", // This lets us know we will need to upgrade it to 3.5 // before upgrading to Solr/Lucene 4.x or above try { oldSegment = Version.parse("3.0"); } catch (ParseException pe) { throw new IOException(pe); } } else if (oldest == null || version.onOrAfter(oldest) == false) { // else if this segment is older than our oldest thus far // We have a new oldest segment version oldest = version; } } // If we found a really old segment, compare it to the oldest // to see which is actually older if (oldSegment != null && oldSegment.onOrAfter(oldest) == false) { oldest = oldSegment; } // At this point, we should know what version of Lucene created our // oldest segment file. We will return this as the Index version // as it's the oldest segment we will need to upgrade. if (oldest != null) { indexVersion = oldest.toString(); } } return indexVersion; } /** * Compare two software version numbers to see which is greater. ONLY does * a comparison of *major* and *minor* versions (any sub-minor versions are * stripped and ignored). *

* This method returns -1 if firstVersion is less than secondVersion, * 1 if firstVersion is greater than secondVersion, and 0 if equal. *

* However, since we ignore sub-minor versions, versions "4.2.1" and "4.2.5" * will be seen as EQUAL (as "4.2" = "4.2"). *

* NOTE: In case it is not obvious, software version numbering does NOT * behave like normal decimal numbers. For example, in software versions * the following statement is TRUE: {@code 4.1 < 4.4 < 4.5 < 4.10 < 4.21 < 4.51} * * @param firstVersion First version to compare, as a String * @param secondVersion Second version to compare as a String * @return -1 if first less than second, 1 if first greater than second, 0 if equal * @throws IOException if IO error */ public static int compareSoftwareVersions(String firstVersion, String secondVersion) throws IOException { // Constants which represent our various return values for this comparison int GREATER_THAN = 1; int EQUAL = 0; int LESS_THAN = -1; // "null" is less than anything if (firstVersion == null) { return LESS_THAN; } // Anything is newer than "null" if (secondVersion == null) { return GREATER_THAN; } //Split the first version into it's parts (i.e. major & minor versions) String[] firstParts = firstVersion.split("\\."); String[] secondParts = secondVersion.split("\\."); // Get major / minor version numbers. Default to "0" if unspecified // NOTE: We are specifically IGNORING any sub-minor version numbers int firstMajor = firstParts.length >= 1 ? Integer.parseInt(firstParts[0]) : 0; int firstMinor = firstParts.length >= 2 ? Integer.parseInt(firstParts[1]) : 0; int secondMajor = secondParts.length >= 1 ? Integer.parseInt(secondParts[0]) : 0; int secondMinor = secondParts.length >= 2 ? Integer.parseInt(secondParts[1]) : 0; // Check for equality if (firstMajor == secondMajor && firstMinor == secondMinor) { return EQUAL; } else if (firstMajor > secondMajor) { // If first major version is greater than second return GREATER_THAN; } else if (firstMajor < secondMajor) { // If first major version is less than second return LESS_THAN; } else if (firstMinor > secondMinor) { // If we get here, major versions must be EQUAL. Now, time to check our minor versions return GREATER_THAN; } else { return LESS_THAN; } } /** * Determine the version of Solr/Lucene which DSpace is currently running. * This is the latest version of Solr/Lucene which we can upgrade the index to. * * @return version as a string (e.g. "4.4") */ public static String getLatestVersion() { // The current version of lucene is in the "LATEST" constant return org.apache.lucene.util.Version.LATEST.toString(); } }





© 2015 - 2024 Weber Informatics LLC | Privacy Policy