blob: ee266a7f1b2c7cddfb5b4bf4ddd9dd8ade1220d7 [file] [log] [blame]
using Lucene.Net.Util;
using System;
using System.Collections.Generic;
using System.IO;
using Console = Lucene.Net.Util.SystemConsole;
namespace Lucene.Net.Index
{
/*
* 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.
*/
using CommandLineUtil = Lucene.Net.Util.CommandLineUtil;
using Constants = Lucene.Net.Util.Constants;
using Directory = Lucene.Net.Store.Directory;
using FSDirectory = Lucene.Net.Store.FSDirectory;
using InfoStream = Lucene.Net.Util.InfoStream;
/// <summary>
/// This is an easy-to-use tool that upgrades all segments of an index from previous Lucene versions
/// to the current segment file format. It can be used from command line:
/// <code>
/// java -cp lucene-core.jar Lucene.Net.Index.IndexUpgrader [-delete-prior-commits] [-verbose] indexDir
/// </code>
/// Alternatively this class can be instantiated and <see cref="Upgrade()"/> invoked. It uses <see cref="UpgradeIndexMergePolicy"/>
/// and triggers the upgrade via an <see cref="IndexWriter.ForceMerge(int)"/> request to <see cref="IndexWriter"/>.
/// <para/>
/// This tool keeps only the last commit in an index; for this
/// reason, if the incoming index has more than one commit, the tool
/// refuses to run by default. Specify <c>-delete-prior-commits</c>
/// to override this, allowing the tool to delete all but the last commit.
/// From .NET code this can be enabled by passing <c>true</c> to
/// <see cref="IndexUpgrader(Directory, LuceneVersion, TextWriter, bool)"/>.
/// <para/>
/// <b>Warning:</b> this tool may reorder documents if the index was partially
/// upgraded before execution (e.g., documents were added). If your application relies
/// on &quot;monotonicity&quot; of doc IDs (which means that the order in which the documents
/// were added to the index is preserved), do a full ForceMerge instead.
/// The <see cref="MergePolicy"/> set by <see cref="IndexWriterConfig"/> may also reorder
/// documents.
/// </summary>
public sealed class IndexUpgrader
{
private static void PrintUsage()
{
// LUCENENET specific - our wrapper console shows the correct usage
throw new ArgumentException();
//Console.Error.WriteLine("Upgrades an index so all segments created with a previous Lucene version are rewritten.");
//Console.Error.WriteLine("Usage:");
//Console.Error.WriteLine(" java " + typeof(IndexUpgrader).Name + " [-delete-prior-commits] [-verbose] [-dir-impl X] indexDir");
//Console.Error.WriteLine("this tool keeps only the last commit in an index; for this");
//Console.Error.WriteLine("reason, if the incoming index has more than one commit, the tool");
//Console.Error.WriteLine("refuses to run by default. Specify -delete-prior-commits to override");
//Console.Error.WriteLine("this, allowing the tool to delete all but the last commit.");
//Console.Error.WriteLine("Specify a " + typeof(FSDirectory).Name + " implementation through the -dir-impl option to force its use. If no package is specified the " + typeof(FSDirectory).Namespace + " package will be used.");
//Console.Error.WriteLine("WARNING: this tool may reorder document IDs!");
//Environment.FailFast("1");
}
/// <summary>
/// Main method to run <see cref="IndexUpgrader"/> from the
/// command-line.
/// </summary>
public static void Main(string[] args)
{
ParseArgs(args).Upgrade();
}
public static IndexUpgrader ParseArgs(string[] args)
{
string path = null;
bool deletePriorCommits = false;
TextWriter @out = null;
string dirImpl = null;
int i = 0;
while (i < args.Length)
{
string arg = args[i];
if ("-delete-prior-commits".Equals(arg, StringComparison.Ordinal))
{
deletePriorCommits = true;
}
else if ("-verbose".Equals(arg, StringComparison.Ordinal))
{
@out = Console.Out;
}
else if ("-dir-impl".Equals(arg, StringComparison.Ordinal))
{
if (i == args.Length - 1)
{
throw new ArgumentException("ERROR: missing value for -dir option");
//Console.WriteLine("ERROR: missing value for -dir-impl option");
//Environment.FailFast("1");
}
i++;
dirImpl = args[i];
}
else if (path == null)
{
path = arg;
}
else
{
PrintUsage();
}
i++;
}
if (path == null)
{
PrintUsage();
}
Directory dir = null;
if (dirImpl == null)
{
dir = FSDirectory.Open(new DirectoryInfo(path));
}
else
{
dir = CommandLineUtil.NewFSDirectory(dirImpl, new DirectoryInfo(path));
}
#pragma warning disable 612, 618
return new IndexUpgrader(dir, LuceneVersion.LUCENE_CURRENT, @out, deletePriorCommits);
#pragma warning restore 612, 618
}
internal readonly Directory dir; // LUCENENET specific - made internal for testing CLI arguments
internal readonly IndexWriterConfig iwc; // LUCENENET specific - made internal for testing CLI arguments
internal readonly bool deletePriorCommits; // LUCENENET specific - made internal for testing CLI arguments
/// <summary>
/// Creates index upgrader on the given directory, using an <see cref="IndexWriter"/> using the given
/// <paramref name="matchVersion"/>. The tool refuses to upgrade indexes with multiple commit points.
/// </summary>
public IndexUpgrader(Directory dir, LuceneVersion matchVersion)
: this(dir, new IndexWriterConfig(matchVersion, null), false)
{
}
/// <summary>
/// Creates index upgrader on the given directory, using an <see cref="IndexWriter"/> using the given
/// <paramref name="matchVersion"/>. You have the possibility to upgrade indexes with multiple commit points by removing
/// all older ones. If <paramref name="infoStream"/> is not <c>null</c>, all logging output will be sent to this stream.
/// </summary>
public IndexUpgrader(Directory dir, LuceneVersion matchVersion, TextWriter infoStream, bool deletePriorCommits)
: this(dir, new IndexWriterConfig(matchVersion, null), deletePriorCommits)
{
if (null != infoStream)
{
this.iwc.SetInfoStream(infoStream);
}
}
/// <summary>
/// Creates index upgrader on the given directory, using an <see cref="IndexWriter"/> using the given
/// config. You have the possibility to upgrade indexes with multiple commit points by removing
/// all older ones.
/// </summary>
public IndexUpgrader(Directory dir, IndexWriterConfig iwc, bool deletePriorCommits)
{
this.dir = dir;
this.iwc = iwc;
this.deletePriorCommits = deletePriorCommits;
}
/// <summary>
/// Perform the upgrade. </summary>
public void Upgrade()
{
if (!DirectoryReader.IndexExists(dir))
{
throw new IndexNotFoundException(dir.ToString());
}
if (!deletePriorCommits)
{
ICollection<IndexCommit> commits = DirectoryReader.ListCommits(dir);
if (commits.Count > 1)
{
throw new ArgumentException("this tool was invoked to not delete prior commit points, but the following commits were found: " + commits);
}
}
IndexWriterConfig c = (IndexWriterConfig)iwc.Clone();
c.MergePolicy = new UpgradeIndexMergePolicy(c.MergePolicy);
c.IndexDeletionPolicy = new KeepOnlyLastCommitDeletionPolicy();
IndexWriter w = new IndexWriter(dir, c);
try
{
InfoStream infoStream = c.InfoStream;
if (infoStream.IsEnabled("IndexUpgrader"))
{
infoStream.Message("IndexUpgrader", "Upgrading all pre-" + Constants.LUCENE_MAIN_VERSION + " segments of index directory '" + dir + "' to version " + Constants.LUCENE_MAIN_VERSION + "...");
}
w.ForceMerge(1);
if (infoStream.IsEnabled("IndexUpgrader"))
{
infoStream.Message("IndexUpgrader", "All segments upgraded to version " + Constants.LUCENE_MAIN_VERSION);
}
}
finally
{
w.Dispose();
}
}
}
}