mirror of https://github.com/apache/lucene.git
LUCENE-2339: deprecate static Directory.copy in favor non-static Directory.copyTo; if it's FSDir -> FSDir, use nio's FileChannel.transferTo
git-svn-id: https://svn.apache.org/repos/asf/lucene/dev/trunk@927761 13f79535-47bb-0310-9956-ffa450edef68
This commit is contained in:
parent
4319c22796
commit
29963c7c7e
|
@ -216,6 +216,11 @@ New features
|
|||
convenient classes in case you want to disable segment merges by IndexWriter
|
||||
without tweaking a particular MergePolicy parameters, such as mergeFactor.
|
||||
MergeScheduler's methods are now public. (Shai Erera via Mike McCandless)
|
||||
|
||||
* LUCENE-2339: Deprecate static method Directory.copy in favor of
|
||||
Directory.copyTo, and use nio's FileChannel.transferTo when copying
|
||||
files between FSDirectory instances. (Earwin Burrfoot via Mike
|
||||
McCandless).
|
||||
|
||||
Optimizations
|
||||
|
||||
|
|
|
@ -22,7 +22,13 @@ import java.io.Closeable;
|
|||
import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import static java.util.Arrays.asList;
|
||||
import java.util.Collection;
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
import org.apache.lucene.index.IndexFileNameFilter;
|
||||
import org.apache.lucene.util.IOUtils;
|
||||
|
||||
/** A Directory is a flat list of files. Files may be written once, when they
|
||||
* are created. Once a file is created it may only be opened for read, or
|
||||
|
@ -183,64 +189,83 @@ public abstract class Directory implements Closeable {
|
|||
return this.toString();
|
||||
}
|
||||
|
||||
/**
|
||||
* Copy contents of a directory src to a directory dest.
|
||||
* If a file in src already exists in dest then the
|
||||
* one in dest will be blindly overwritten.
|
||||
*
|
||||
* <p><b>NOTE:</b> the source directory cannot change
|
||||
* while this method is running. Otherwise the results
|
||||
* are undefined and you could easily hit a
|
||||
* FileNotFoundException.
|
||||
*
|
||||
* <p><b>NOTE:</b> this method only copies files that look
|
||||
* like index files (ie, have extensions matching the
|
||||
* known extensions of index files).
|
||||
*
|
||||
* @param src source directory
|
||||
* @param dest destination directory
|
||||
* @param closeDirSrc if <code>true</code>, call {@link #close()} method on source directory
|
||||
* @throws IOException
|
||||
*/
|
||||
public static void copy(Directory src, Directory dest, boolean closeDirSrc) throws IOException {
|
||||
final String[] files = src.listAll();
|
||||
|
||||
/**
|
||||
* <p>Copy all files of this directory to destination directory. All conflicting files at destination are overwritten</p>
|
||||
* <p><b>NOTE:</b> this method only copies files that look like index files (ie, have extensions matching the known
|
||||
* extensions of index files).
|
||||
* <p><b>NOTE:</b> the source directory should not change while this method is running. Otherwise the results are
|
||||
* undefined and you could easily hit a FileNotFoundException. </p>
|
||||
*
|
||||
* @param to destination directory
|
||||
*/
|
||||
public final void copyTo(Directory to) throws IOException {
|
||||
List<String> filenames = new ArrayList<String>();
|
||||
IndexFileNameFilter filter = IndexFileNameFilter.getFilter();
|
||||
|
||||
for (String name : listAll())
|
||||
if (filter.accept(null, name))
|
||||
filenames.add(name);
|
||||
|
||||
copyTo(to, filenames);
|
||||
}
|
||||
|
||||
/**
|
||||
* <p>Copy given files of this directory to destination directory. All conflicting files at destination are overwritten</p>
|
||||
* <p><b>NOTE:</b> the source directory should not change while this method is running. Otherwise the results are
|
||||
* undefined and you could easily hit a FileNotFoundException. </p>
|
||||
* <p><b>NOTE:</b> implementations can check if destination directory is of the same type as 'this' and perform optimized copy</p>
|
||||
*
|
||||
* @param to destination directory
|
||||
* @param filenames file names to be copied
|
||||
*/
|
||||
public void copyTo(Directory to, Collection<String> filenames) throws IOException {
|
||||
byte[] buf = new byte[BufferedIndexOutput.BUFFER_SIZE];
|
||||
for (int i = 0; i < files.length; i++) {
|
||||
|
||||
if (!filter.accept(null, files[i]))
|
||||
continue;
|
||||
|
||||
for (String filename : filenames) {
|
||||
IndexOutput os = null;
|
||||
IndexInput is = null;
|
||||
IOException priorException = null;
|
||||
try {
|
||||
// create file in dest directory
|
||||
os = dest.createOutput(files[i]);
|
||||
os = to.createOutput(filename);
|
||||
// read current file
|
||||
is = src.openInput(files[i]);
|
||||
is = openInput(filename);
|
||||
// and copy to dest directory
|
||||
long len = is.length();
|
||||
long readCount = 0;
|
||||
while (readCount < len) {
|
||||
int toRead = readCount + BufferedIndexOutput.BUFFER_SIZE > len ? (int)(len - readCount) : BufferedIndexOutput.BUFFER_SIZE;
|
||||
int toRead = readCount + BufferedIndexOutput.BUFFER_SIZE > len ? (int) (len - readCount) : BufferedIndexOutput.BUFFER_SIZE;
|
||||
is.readBytes(buf, 0, toRead);
|
||||
os.writeBytes(buf, toRead);
|
||||
readCount += toRead;
|
||||
}
|
||||
} catch (IOException ioe) {
|
||||
priorException = ioe;
|
||||
} finally {
|
||||
// graceful cleanup
|
||||
try {
|
||||
if (os != null)
|
||||
os.close();
|
||||
} finally {
|
||||
if (is != null)
|
||||
is.close();
|
||||
}
|
||||
IOUtils.closeSafely(priorException, os, is);
|
||||
}
|
||||
}
|
||||
if(closeDirSrc)
|
||||
}
|
||||
|
||||
/**
|
||||
* Copy contents of a directory src to a directory dest. If a file in src already exists in dest then the one in dest
|
||||
* will be blindly overwritten.
|
||||
* <p/>
|
||||
* <p><b>NOTE:</b> the source directory cannot change while this method is running. Otherwise the results are
|
||||
* undefined and you could easily hit a FileNotFoundException.
|
||||
* <p/>
|
||||
* <p><b>NOTE:</b> this method only copies files that look like index files (ie, have extensions matching the known
|
||||
* extensions of index files).
|
||||
*
|
||||
* @param src source directory
|
||||
* @param dest destination directory
|
||||
* @param closeDirSrc if <code>true</code>, call {@link #close()} method on source directory
|
||||
* @deprecated should be replaced with src.copyTo(dest); [src.close();]
|
||||
*/
|
||||
@Deprecated
|
||||
public static void copy(Directory src, Directory dest, boolean closeDirSrc) throws IOException {
|
||||
src.copyTo(dest);
|
||||
if (closeDirSrc)
|
||||
src.close();
|
||||
}
|
||||
|
||||
|
|
|
@ -18,9 +18,12 @@ package org.apache.lucene.store;
|
|||
*/
|
||||
|
||||
import java.io.File;
|
||||
import java.io.FileInputStream;
|
||||
import java.io.FileOutputStream;
|
||||
import java.io.FilenameFilter;
|
||||
import java.io.IOException;
|
||||
import java.io.RandomAccessFile;
|
||||
import java.nio.channels.FileChannel;
|
||||
import java.security.MessageDigest;
|
||||
import java.security.NoSuchAlgorithmException;
|
||||
|
||||
|
@ -29,6 +32,7 @@ import java.util.Collections;
|
|||
import static java.util.Collections.synchronizedSet;
|
||||
import java.util.HashSet;
|
||||
import java.util.Set;
|
||||
import org.apache.lucene.util.IOUtils;
|
||||
import org.apache.lucene.util.ThreadInterruptedException;
|
||||
import org.apache.lucene.util.Constants;
|
||||
|
||||
|
@ -422,6 +426,30 @@ public abstract class FSDirectory extends Directory {
|
|||
return chunkSize;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void copyTo(Directory to, Collection<String> filenames) throws IOException {
|
||||
if (to instanceof FSDirectory) {
|
||||
FSDirectory target = (FSDirectory) to;
|
||||
|
||||
for (String filename : filenames) {
|
||||
target.ensureCanWrite(filename);
|
||||
FileChannel input = null;
|
||||
FileChannel output = null;
|
||||
IOException priorException = null;
|
||||
try {
|
||||
input = new FileInputStream(new File(directory, filename)).getChannel();
|
||||
output = new FileOutputStream(new File(target.directory, filename)).getChannel();
|
||||
output.transferFrom(input, 0, input.size());
|
||||
} catch (IOException ioe) {
|
||||
priorException = ioe;
|
||||
} finally {
|
||||
IOUtils.closeSafely(priorException, input, output);
|
||||
}
|
||||
}
|
||||
} else
|
||||
super.copyTo(to, filenames);
|
||||
}
|
||||
|
||||
protected static class FSIndexOutput extends BufferedIndexOutput {
|
||||
private final FSDirectory parent;
|
||||
private final String name;
|
||||
|
|
|
@ -0,0 +1,64 @@
|
|||
package org.apache.lucene.util;
|
||||
|
||||
/**
|
||||
* 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.
|
||||
*/
|
||||
|
||||
import java.io.Closeable;
|
||||
import java.io.IOException;
|
||||
|
||||
/** @lucene.internal */
|
||||
public class IOUtils {
|
||||
/**
|
||||
* <p>Closes all given <tt>Closeable</tt>s, suppressing all thrown exceptions. Some of the <tt>Closeable</tt>s
|
||||
* may be null, they are ignored. After everything is closed, method either throws <tt>priorException</tt>,
|
||||
* if one is supplied, or the first of suppressed exceptions, or completes normally.</p>
|
||||
* <p>Sample usage:<br/>
|
||||
* <pre>
|
||||
* Closeable resource1 = null, resource2 = null, resource3 = null;
|
||||
* ExpectedException priorE = null;
|
||||
* try {
|
||||
* resource1 = ...; resource2 = ...; resource3 = ...; // Aquisition may throw ExpectedException
|
||||
* ..do..stuff.. // May throw ExpectedException
|
||||
* } catch (ExpectedException e) {
|
||||
* priorE = e;
|
||||
* } finally {
|
||||
* closeSafely(priorE, resource1, resource2, resource3);
|
||||
* }
|
||||
* </pre>
|
||||
* </p>
|
||||
* @param priorException <tt>null</tt> or an exception that will be rethrown after method completion
|
||||
* @param objects objects to call <tt>close()</tt> on
|
||||
*/
|
||||
public static <E extends Exception> void closeSafely(E priorException, Closeable... objects) throws E, IOException {
|
||||
IOException firstIOE = null;
|
||||
|
||||
for (Closeable object : objects) {
|
||||
try {
|
||||
if (object != null)
|
||||
object.close();
|
||||
} catch (IOException ioe) {
|
||||
if (firstIOE == null)
|
||||
firstIOE = ioe;
|
||||
}
|
||||
}
|
||||
|
||||
if (priorException != null)
|
||||
throw priorException;
|
||||
else if (firstIOE != null)
|
||||
throw firstIOE;
|
||||
}
|
||||
}
|
|
@ -17,7 +17,7 @@ public class RefCntRamDirectory extends RAMDirectory {
|
|||
|
||||
public RefCntRamDirectory(Directory dir) throws IOException {
|
||||
this();
|
||||
Directory.copy(dir, this, false);
|
||||
dir.copyTo(this);
|
||||
}
|
||||
|
||||
public void incRef() {
|
||||
|
|
Loading…
Reference in New Issue