mirror of https://github.com/apache/lucene.git
LUCENE-6957: add missing NRTCachingDirectory.createTempOutput
git-svn-id: https://svn.apache.org/repos/asf/lucene/dev/trunk@1723259 13f79535-47bb-0310-9956-ffa450edef68
This commit is contained in:
parent
32330252b9
commit
2aa14f92d2
|
@ -17,11 +17,15 @@ package org.apache.lucene.store;
|
||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
import java.io.FileNotFoundException;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
|
import java.nio.file.NoSuchFileException;
|
||||||
|
import java.util.ArrayList;
|
||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
import java.util.Collection;
|
import java.util.Collection;
|
||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
import java.util.HashSet;
|
import java.util.HashSet;
|
||||||
|
import java.util.List;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
|
|
||||||
import org.apache.lucene.store.RAMDirectory; // javadocs
|
import org.apache.lucene.store.RAMDirectory; // javadocs
|
||||||
|
@ -175,7 +179,6 @@ public class NRTCachingDirectory extends FilterDirectory implements Accountable
|
||||||
in.renameFile(source, dest);
|
in.renameFile(source, dest);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public synchronized IndexInput openInput(String name, IOContext context) throws IOException {
|
public synchronized IndexInput openInput(String name, IOContext context) throws IOException {
|
||||||
if (VERBOSE) {
|
if (VERBOSE) {
|
||||||
|
@ -232,6 +235,64 @@ public class NRTCachingDirectory extends FilterDirectory implements Accountable
|
||||||
return (bytes <= maxMergeSizeBytes) && (bytes + cache.ramBytesUsed()) <= maxCachedBytes;
|
return (bytes <= maxMergeSizeBytes) && (bytes + cache.ramBytesUsed()) <= maxCachedBytes;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public IndexOutput createTempOutput(String prefix, String suffix, IOContext context) throws IOException {
|
||||||
|
if (VERBOSE) {
|
||||||
|
System.out.println("nrtdir.createTempOutput prefix=" + prefix + " suffix=" + suffix);
|
||||||
|
}
|
||||||
|
List<String> toDelete = new ArrayList<>();
|
||||||
|
|
||||||
|
// This is very ugly/messy/dangerous (can in some disastrous case maybe create too many temp files), but I don't know of a cleaner way:
|
||||||
|
boolean success = false;
|
||||||
|
|
||||||
|
Directory first;
|
||||||
|
Directory second;
|
||||||
|
if (doCacheWrite(prefix, context)) {
|
||||||
|
first = cache;
|
||||||
|
second = in;
|
||||||
|
} else {
|
||||||
|
first = in;
|
||||||
|
second = cache;
|
||||||
|
}
|
||||||
|
|
||||||
|
IndexOutput out = null;
|
||||||
|
try {
|
||||||
|
while (true) {
|
||||||
|
out = first.createTempOutput(prefix, suffix, context);
|
||||||
|
String name = out.getName();
|
||||||
|
toDelete.add(name);
|
||||||
|
if (slowFileExists(second, name)) {
|
||||||
|
out.close();
|
||||||
|
} else {
|
||||||
|
success = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} finally {
|
||||||
|
if (success) {
|
||||||
|
IOUtils.deleteFiles(first, toDelete);
|
||||||
|
} else {
|
||||||
|
IOUtils.closeWhileHandlingException(out);
|
||||||
|
IOUtils.deleteFilesIgnoringExceptions(first, toDelete);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return out;
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Returns true if the file exists
|
||||||
|
* (can be opened), false if it cannot be opened, and
|
||||||
|
* (unlike Java's File.exists) throws IOException if
|
||||||
|
* there's some unexpected error. */
|
||||||
|
static boolean slowFileExists(Directory dir, String fileName) throws IOException {
|
||||||
|
try {
|
||||||
|
dir.openInput(fileName, IOContext.DEFAULT).close();
|
||||||
|
return true;
|
||||||
|
} catch (NoSuchFileException | FileNotFoundException e) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private final Object uncacheLock = new Object();
|
private final Object uncacheLock = new Object();
|
||||||
|
|
||||||
private void unCache(String fileName) throws IOException {
|
private void unCache(String fileName) throws IOException {
|
||||||
|
@ -245,6 +306,8 @@ public class NRTCachingDirectory extends FilterDirectory implements Accountable
|
||||||
// Another thread beat us...
|
// Another thread beat us...
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
assert slowFileExists(in, fileName) == false: "fileName=" + fileName + " exists both in cache and in delegate";
|
||||||
|
|
||||||
final IOContext context = IOContext.DEFAULT;
|
final IOContext context = IOContext.DEFAULT;
|
||||||
final IndexOutput out = in.createOutput(fileName, context);
|
final IndexOutput out = in.createOutput(fileName, context);
|
||||||
IndexInput in = null;
|
IndexInput in = null;
|
||||||
|
|
|
@ -122,4 +122,18 @@ public class TestNRTCachingDirectory extends BaseDirectoryTestCase {
|
||||||
writer.close();
|
writer.close();
|
||||||
cachedFSDir.close();
|
cachedFSDir.close();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void testCreateTempOutput() throws Exception {
|
||||||
|
|
||||||
|
Directory fsDir = FSDirectory.open(createTempDir("verify"));
|
||||||
|
NRTCachingDirectory nrtDir = new NRTCachingDirectory(fsDir, 2.0, 25.0);
|
||||||
|
String name = "foo_bar_0.tmp";
|
||||||
|
nrtDir.createOutput(name, IOContext.DEFAULT).close();
|
||||||
|
|
||||||
|
IndexOutput out = nrtDir.createTempOutput("foo", "bar", IOContext.DEFAULT);
|
||||||
|
assertFalse(name.equals(out.getName()));
|
||||||
|
out.close();
|
||||||
|
nrtDir.close();
|
||||||
|
fsDir.close();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue