pylucene 3.5.0-3
[pylucene.git] / lucene-java-3.5.0 / lucene / contrib / misc / src / java / org / apache / lucene / index / IndexSplitter.java
1 /**
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
8  *
9  *     http://www.apache.org/licenses/LICENSE-2.0
10  *
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.
16  */
17 package org.apache.lucene.index;
18
19 import java.io.File;
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;
28
29 import org.apache.lucene.index.IndexWriter;       // javadocs
30 import org.apache.lucene.store.FSDirectory;
31
32 /**
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.
36  *
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 a
40  * single segment, 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>
44  *
45  * @lucene.experimental You can easily
46  * accidentally remove segments from your index so be
47  * careful!
48  *
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.
53  */
54 public class IndexSplitter {
55   public SegmentInfos infos;
56
57   FSDirectory fsDir;
58
59   File dir;
60
61   /**
62    * @param args
63    */
64   public static void main(String[] args) throws Exception {
65     if (args.length < 2) {
66       System.err
67           .println("Usage: IndexSplitter <srcDir> -l (list the segments and their sizes)");
68       System.err.println("IndexSplitter <srcDir> <destDir> <segments>+");
69       System.err
70           .println("IndexSplitter <srcDir> -d (delete the following segments)");
71       return;
72     }
73     File srcDir = new File(args[0]);
74     IndexSplitter is = new IndexSplitter(srcDir);
75     if (!srcDir.exists()) {
76       throw new Exception("srcdir:" + srcDir.getAbsolutePath()
77           + " doesn't exist");
78     }
79     if (args[1].equals("-l")) {
80       is.listSegments();
81     } else if (args[1].equals("-d")) {
82       List<String> segs = new ArrayList<String>();
83       for (int x = 2; x < args.length; x++) {
84         segs.add(args[x]);
85       }
86       is.remove(segs.toArray(new String[0]));
87     } else {
88       File targetDir = new File(args[1]);
89       List<String> segs = new ArrayList<String>();
90       for (int x = 2; x < args.length; x++) {
91         segs.add(args[x]);
92       }
93       is.split(targetDir, segs.toArray(new String[0]));
94     }
95   }
96
97   public IndexSplitter(File dir) throws IOException {
98     this.dir = dir;
99     fsDir = FSDirectory.open(dir);
100     infos = new SegmentInfos();
101     infos.read(fsDir);
102   }
103
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);
110     }
111   }
112
113   private int getIdx(String name) {
114     for (int x = 0; x < infos.size(); x++) {
115       if (name.equals(infos.info(x).name))
116         return x;
117     }
118     return -1;
119   }
120
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);
125     }
126     return null;
127   }
128
129   public void remove(String[] segs) throws IOException {
130     for (String n : segs) {
131       int idx = getIdx(n);
132       infos.remove(idx);
133     }
134     infos.changed();
135     infos.commit(fsDir);
136   }
137
138   public void split(File destDir, String[] segs) throws IOException {
139     destDir.mkdirs();
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);
145       destInfos.add(info);
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);
152       }
153     }
154     destInfos.changed();
155     destInfos.commit(destFSDir);
156     // System.out.println("destDir:"+destDir.getAbsolutePath());
157   }
158
159   private static final byte[] copyBuffer = new byte[32*1024];
160
161   private static void copyFile(File src, File dst) throws IOException {
162     InputStream in = new FileInputStream(src);
163     OutputStream out = new FileOutputStream(dst);
164     int len;
165     while ((len = in.read(copyBuffer)) > 0) {
166       out.write(copyBuffer, 0, len);
167     }
168     in.close();
169     out.close();
170   }
171 }