2 * Licensed to the Apache Software Foundation (ASF) under one or more
3 * contributor license agreements. See the NOTICE file distributed with
4 * this work for additional information regarding copyright ownership.
5 * The ASF licenses this file to You under the Apache License, Version 2.0
6 * (the "License"); you may not use this file except in compliance with
7 * the License. You may obtain a copy of the License at
9 * http://www.apache.org/licenses/LICENSE-2.0
11 * Unless required by applicable law or agreed to in writing, software
12 * distributed under the License is distributed on an "AS IS" BASIS,
13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 * See the License for the specific language governing permissions and
15 * limitations under the License.
17 package org.apache.lucene.index;
20 import java.io.FileInputStream;
21 import java.io.FileOutputStream;
22 import java.io.IOException;
23 import java.io.InputStream;
24 import java.io.OutputStream;
25 import java.text.DecimalFormat;
26 import java.util.ArrayList;
27 import java.util.List;
29 import org.apache.lucene.index.IndexWriter; // javadocs
30 import org.apache.lucene.store.FSDirectory;
33 * Command-line tool that enables listing segments in an
34 * index, copying specific segments to another index, and
35 * deleting segments from an index.
37 * <p>This tool does file-level copying of segments files.
38 * This means it's unable to split apart a single segment
39 * into multiple segments. For example if your index is
40 * optimized, this tool won't help. Also, it does basic
41 * file-level copying (using simple
42 * File{In,Out}putStream) so it will not work with non
43 * FSDirectory Directory impls.</p>
45 * @lucene.experimental You can easily
46 * accidentally remove segments from your index so be
49 * <p><b>NOTE</b>: this tool is unaware of documents added
50 * atomically via {@link IndexWriter#addDocuments} or {@link
51 * IndexWriter#updateDocuments}, which means it can easily
52 * break up such document groups.
54 public class IndexSplitter {
55 public SegmentInfos infos;
64 public static void main(String[] args) throws Exception {
65 if (args.length < 2) {
67 .println("Usage: IndexSplitter <srcDir> -l (list the segments and their sizes)");
68 System.err.println("IndexSplitter <srcDir> <destDir> <segments>+");
70 .println("IndexSplitter <srcDir> -d (delete the following segments)");
73 File srcDir = new File(args[0]);
74 IndexSplitter is = new IndexSplitter(srcDir);
75 if (!srcDir.exists()) {
76 throw new Exception("srcdir:" + srcDir.getAbsolutePath()
79 if (args[1].equals("-l")) {
81 } else if (args[1].equals("-d")) {
82 List<String> segs = new ArrayList<String>();
83 for (int x = 2; x < args.length; x++) {
86 is.remove(segs.toArray(new String[0]));
88 File targetDir = new File(args[1]);
89 List<String> segs = new ArrayList<String>();
90 for (int x = 2; x < args.length; x++) {
93 is.split(targetDir, segs.toArray(new String[0]));
97 public IndexSplitter(File dir) throws IOException {
99 fsDir = FSDirectory.open(dir);
100 infos = new SegmentInfos();
104 public void listSegments() throws IOException {
105 DecimalFormat formatter = new DecimalFormat("###,###.###");
106 for (int x = 0; x < infos.size(); x++) {
107 SegmentInfo info = infos.info(x);
108 String sizeStr = formatter.format(info.sizeInBytes(true));
109 System.out.println(info.name + " " + sizeStr);
113 private int getIdx(String name) {
114 for (int x = 0; x < infos.size(); x++) {
115 if (name.equals(infos.info(x).name))
121 private SegmentInfo getInfo(String name) {
122 for (int x = 0; x < infos.size(); x++) {
123 if (name.equals(infos.info(x).name))
124 return infos.info(x);
129 public void remove(String[] segs) throws IOException {
130 for (String n : segs) {
138 public void split(File destDir, String[] segs) throws IOException {
140 FSDirectory destFSDir = FSDirectory.open(destDir);
141 SegmentInfos destInfos = new SegmentInfos();
142 destInfos.counter = infos.counter;
143 for (String n : segs) {
144 SegmentInfo info = getInfo(n);
146 // now copy files over
147 List<String> files = info.files();
148 for (final String srcName : files) {
149 File srcFile = new File(dir, srcName);
150 File destFile = new File(destDir, srcName);
151 copyFile(srcFile, destFile);
155 destInfos.commit(destFSDir);
156 // System.out.println("destDir:"+destDir.getAbsolutePath());
159 private static final byte[] copyBuffer = new byte[32*1024];
161 private static void copyFile(File src, File dst) throws IOException {
162 InputStream in = new FileInputStream(src);
163 OutputStream out = new FileOutputStream(dst);
165 while ((len = in.read(copyBuffer)) > 0) {
166 out.write(copyBuffer, 0, len);