All,

On 2025/09/14 16:49:16 Christopher Schultz wrote:
> I've written (with some help from ChatGPT) a short CLI utility to check 
> the segments and segment info and optionally force a change to the major 
> version. It should only work if the requested version is *higher* than 
> the current version AND if all the segments are already compatible. You 
> also have to use a command-line argument to enable WRITE mode.
> 
> So, you can run it on an index and get info, and verify beforehand that 
> it SHOULD work before asking it to actually write to the segment info 
> and "forge" the new indexCreatedVersionMajor field.

I have made a few modifications and actually run this on a test index 
originally created with Solr/Lucene 7, but running on Solr 8. There were no 
issues stopping Solr 8, running this to force the index to move to version 8, 
then restarting Solr. Everything works as expected.

My next step is to try running this newly-forged index on Solr 9.

Here is the latest code:

import org.apache.lucene.index.*;
import org.apache.lucene.store.FSDirectory;
import org.apache.lucene.util.Version;

import java.io.IOException;
import java.lang.reflect.Field;
import java.nio.file.Path;
import java.nio.file.Paths;

public class LuceneIndexUpgrader {

    public static void main(String[] args) {
        if (args.length < 1) {
            System.err.println("Usage: java LuceneIndexUpgrader <path-to-index> 
[newMajorVersion] [--write]");
            System.exit(1);
        }

        Path indexPath = null;
        Integer newMajorVersion = null;
        boolean shouldWrite = false;

        // Parse args
        for (String arg : args) {
            if (arg.equals("--write")) {
                shouldWrite = true;
            } else if (arg.matches("\\d+")) {
                newMajorVersion = Integer.parseInt(arg);
            } else if (indexPath == null) {
                indexPath = Paths.get(arg);
            } else {
                System.err.println("Unrecognized argument: " + arg);
                System.exit(1);
            }
        }

        if (indexPath == null) {
            System.err.println("Error: Index path is required.");
            System.exit(1);
        }

        if (newMajorVersion != null && (newMajorVersion < 1 || newMajorVersion 
> 99)) {
            System.err.println("Invalid Lucene major version: " + 
newMajorVersion);
            System.exit(1);
        }

        // Get Lucene library version
        Version luceneVersion = Version.LATEST;
        int currentLuceneMajor = luceneVersion.major;

        System.out.println("Running with Lucene library version: " + 
luceneVersion);

        if (newMajorVersion != null && newMajorVersion > currentLuceneMajor) {
            System.err.printf(
                "Aborting: Requested index version %d is higher than the 
current Lucene library version %d%n",
                newMajorVersion, currentLuceneMajor
            );
            System.exit(1);
        }

        try (FSDirectory directory = FSDirectory.open(indexPath)) {
            SegmentInfos segmentInfos = 
SegmentInfos.readLatestCommit(directory);

            int currentMajorVersion = 
segmentInfos.getIndexCreatedVersionMajor();

            // Print index-level version info
            System.out.println("\nLucene Index Metadata:");
            
System.out.println("--------------------------------------------------");
            System.out.println("Index Created Version Major: " + 
currentMajorVersion);
            System.out.println("Min Segment Lucene Version: " + 
segmentInfos.getMinSegmentLuceneVersion());

            System.out.println("\nSegment Details:");
            boolean compatible = true;

            for (SegmentCommitInfo sci : segmentInfos) {
                SegmentInfo si = sci.info;
                Version version = si.getVersion();
                Version minVersion = si.getMinVersion();

                
System.out.println("--------------------------------------------------");
                System.out.println("Segment name:       " + si.name);
                System.out.println("  Lucene version:   " + version);
                System.out.println("  Min Lucene ver:   " + minVersion);

                if (newMajorVersion != null) {
                    int actualVersion = minVersion != null ? minVersion.major :
                            (version != null ? version.major : -1);

                    if (actualVersion < newMajorVersion) {
                        System.err.printf("  Incompatible: segment minVersion 
%d < requested indexCreatedVersionMajor %d%n",
                                actualVersion, newMajorVersion);
                        compatible = false;
                    }
                }
            }

            if (newMajorVersion != null) {
                System.out.printf("\nRequested new indexCreatedVersionMajor: 
%d%n", newMajorVersion);

                // Check: new version not lower than current
                if (newMajorVersion < currentMajorVersion) {
                    System.err.printf("Aborting: new major version %d is less 
than current index version %d%n",
                            newMajorVersion, currentMajorVersion);
                    System.exit(1);
                }

                // Check: new version same as current
                if (newMajorVersion.equals(currentMajorVersion)) {
                    System.out.println("No change needed: index already has the 
requested version.");
                    return;
                }

                if (!compatible) {
                    System.err.println("Aborting: Not all segments are 
compatible with the requested version.");
                    System.exit(1);
                }

                if (shouldWrite) {
                    // Proceed with update
                    Field field = 
SegmentInfos.class.getDeclaredField("indexCreatedVersionMajor");
                    field.setAccessible(true);
                    field.setInt(segmentInfos, newMajorVersion);
                    segmentInfos.commit(directory);

                    System.out.printf("Updated indexCreatedVersionMajor to %d 
and saved to disk.%n", newMajorVersion);
                } else {
                    System.out.println("Dry run: indexCreatedVersionMajor would 
be updated, but --write was not set.");
                }
            } else {
                System.out.println("\n(No version change requested.)");
            }

        } catch (IOException | NoSuchFieldException | IllegalAccessException e) 
{
            System.err.println("Error while processing Lucene index: " + 
e.getMessage());
            e.printStackTrace();
        }
    }
}

Reply via email to