mirror of https://github.com/apache/lucene.git
LUCENE-820: improve MockRAMDirectory to mimic Windows (can't delete open files); added test case for this bug (this root cause of this bug was already fixed by the fix to LUCENE-821)
git-svn-id: https://svn.apache.org/repos/asf/lucene/java/trunk@514370 13f79535-47bb-0310-9956-ffa450edef68
This commit is contained in:
parent
e6a9d9b318
commit
4081e733b1
|
@ -173,7 +173,7 @@ public class RAMDirectory extends Directory implements Serializable {
|
|||
/** Removes an existing file in the directory.
|
||||
* @throws IOException if the file does not exist
|
||||
*/
|
||||
public synchronized final void deleteFile(String name) throws IOException {
|
||||
public synchronized void deleteFile(String name) throws IOException {
|
||||
RAMFile file = (RAMFile)fileMap.get(name);
|
||||
if (file!=null) {
|
||||
fileMap.remove(name);
|
||||
|
@ -215,7 +215,7 @@ public class RAMDirectory extends Directory implements Serializable {
|
|||
}
|
||||
|
||||
/** Returns a stream reading an existing file. */
|
||||
public final IndexInput openInput(String name) throws IOException {
|
||||
public IndexInput openInput(String name) throws IOException {
|
||||
RAMFile file;
|
||||
synchronized (this) {
|
||||
file = (RAMFile)fileMap.get(name);
|
||||
|
|
|
@ -386,6 +386,38 @@ public class TestIndexReader extends TestCase
|
|||
}
|
||||
|
||||
|
||||
// Make sure you can set norms & commit, and there are
|
||||
// no extra norms files left:
|
||||
public void testWritingNormsNoReader() throws IOException
|
||||
{
|
||||
Directory dir = new MockRAMDirectory();
|
||||
IndexWriter writer = null;
|
||||
IndexReader reader = null;
|
||||
Term searchTerm = new Term("content", "aaa");
|
||||
|
||||
// add 1 documents with term : aaa
|
||||
writer = new IndexWriter(dir, new WhitespaceAnalyzer(), true);
|
||||
writer.setUseCompoundFile(false);
|
||||
addDoc(writer, searchTerm.text());
|
||||
writer.close();
|
||||
|
||||
// now open reader & set norm for doc 0 (writes to
|
||||
// _0_1.s0)
|
||||
reader = IndexReader.open(dir);
|
||||
reader.setNorm(0, "content", (float) 2.0);
|
||||
reader.close();
|
||||
|
||||
// now open reader again & set norm for doc 0 (writes to _0_2.s0)
|
||||
reader = IndexReader.open(dir);
|
||||
reader.setNorm(0, "content", (float) 2.0);
|
||||
reader.close();
|
||||
assertFalse("failed to remove first generation norms file on writing second generation",
|
||||
dir.fileExists("_0_1.s0"));
|
||||
|
||||
dir.close();
|
||||
}
|
||||
|
||||
|
||||
public void testDeleteReaderWriterConflictUnoptimized() throws IOException{
|
||||
deleteReaderWriterConflict(false);
|
||||
}
|
||||
|
|
|
@ -19,8 +19,11 @@ package org.apache.lucene.store;
|
|||
|
||||
import java.io.IOException;
|
||||
import java.io.File;
|
||||
import java.io.FileNotFoundException;
|
||||
import java.util.Iterator;
|
||||
import java.util.Random;
|
||||
import java.util.Map;
|
||||
import java.util.HashMap;
|
||||
|
||||
/**
|
||||
* This is a subclass of RAMDirectory that adds methods
|
||||
|
@ -35,18 +38,37 @@ public class MockRAMDirectory extends RAMDirectory {
|
|||
long maxUsedSize;
|
||||
double randomIOExceptionRate;
|
||||
Random randomState;
|
||||
boolean noDeleteOpenFile = true;
|
||||
|
||||
// NOTE: we cannot initialize the Map here due to the
|
||||
// order in which our constructor actually does this
|
||||
// member initialization vs when it calls super. It seems
|
||||
// like super is called, then our members are initialized:
|
||||
Map openFiles;
|
||||
|
||||
public MockRAMDirectory() throws IOException {
|
||||
super();
|
||||
if (openFiles == null) {
|
||||
openFiles = new HashMap();
|
||||
}
|
||||
}
|
||||
public MockRAMDirectory(String dir) throws IOException {
|
||||
super(dir);
|
||||
if (openFiles == null) {
|
||||
openFiles = new HashMap();
|
||||
}
|
||||
}
|
||||
public MockRAMDirectory(Directory dir) throws IOException {
|
||||
super(dir);
|
||||
if (openFiles == null) {
|
||||
openFiles = new HashMap();
|
||||
}
|
||||
}
|
||||
public MockRAMDirectory(File dir) throws IOException {
|
||||
super(dir);
|
||||
if (openFiles == null) {
|
||||
openFiles = new HashMap();
|
||||
}
|
||||
}
|
||||
|
||||
public void setMaxSizeInBytes(long maxSize) {
|
||||
|
@ -67,6 +89,17 @@ public class MockRAMDirectory extends RAMDirectory {
|
|||
this.maxUsedSize = getRecomputedActualSizeInBytes();
|
||||
}
|
||||
|
||||
/**
|
||||
* Emulate windows whereby deleting an open file is not
|
||||
* allowed (raise IOException).
|
||||
*/
|
||||
public void setNoDeleteOpenFile(boolean value) {
|
||||
this.noDeleteOpenFile = value;
|
||||
}
|
||||
public boolean getNoDeleteOpenFile() {
|
||||
return noDeleteOpenFile;
|
||||
}
|
||||
|
||||
/**
|
||||
* If 0.0, no exceptions will be thrown. Else this should
|
||||
* be a double 0.0 - 1.0. We will randomly throw an
|
||||
|
@ -91,7 +124,26 @@ public class MockRAMDirectory extends RAMDirectory {
|
|||
}
|
||||
}
|
||||
|
||||
public synchronized void deleteFile(String name) throws IOException {
|
||||
synchronized(openFiles) {
|
||||
if (noDeleteOpenFile && openFiles.containsKey(name)) {
|
||||
throw new IOException("MockRAMDirectory: file \"" + name + "\" is still open: cannot delete");
|
||||
}
|
||||
}
|
||||
super.deleteFile(name);
|
||||
}
|
||||
|
||||
public IndexOutput createOutput(String name) {
|
||||
if (openFiles == null) {
|
||||
openFiles = new HashMap();
|
||||
}
|
||||
synchronized(openFiles) {
|
||||
if (noDeleteOpenFile && openFiles.containsKey(name)) {
|
||||
// RuntimeException instead of IOException because
|
||||
// super() does not throw IOException currently:
|
||||
throw new RuntimeException("MockRAMDirectory: file \"" + name + "\" is still open: cannot overwrite");
|
||||
}
|
||||
}
|
||||
RAMFile file = new RAMFile(this);
|
||||
synchronized (this) {
|
||||
RAMFile existing = (RAMFile)fileMap.get(name);
|
||||
|
@ -105,6 +157,27 @@ public class MockRAMDirectory extends RAMDirectory {
|
|||
return new MockRAMOutputStream(this, file);
|
||||
}
|
||||
|
||||
public IndexInput openInput(String name) throws IOException {
|
||||
RAMFile file;
|
||||
synchronized (this) {
|
||||
file = (RAMFile)fileMap.get(name);
|
||||
}
|
||||
if (file == null)
|
||||
throw new FileNotFoundException(name);
|
||||
else {
|
||||
synchronized(openFiles) {
|
||||
if (openFiles.containsKey(name)) {
|
||||
Integer v = (Integer) openFiles.get(name);
|
||||
v = new Integer(v.intValue()+1);
|
||||
openFiles.put(name, v);
|
||||
} else {
|
||||
openFiles.put(name, new Integer(1));
|
||||
}
|
||||
}
|
||||
}
|
||||
return new MockRAMInputStream(this, name, file);
|
||||
}
|
||||
|
||||
/** Provided for testing purposes. Use sizeInBytes() instead. */
|
||||
public synchronized final long getRecomputedSizeInBytes() {
|
||||
long size = 0;
|
||||
|
|
|
@ -0,0 +1,62 @@
|
|||
package org.apache.lucene.store;
|
||||
|
||||
/**
|
||||
* 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.
|
||||
*/
|
||||
|
||||
/**
|
||||
* Used by MockRAMDirectory to create an input stream that
|
||||
* keeps track of when it's been closed.
|
||||
*/
|
||||
|
||||
public class MockRAMInputStream extends RAMInputStream {
|
||||
private MockRAMDirectory dir;
|
||||
private String name;
|
||||
|
||||
/** Construct an empty output buffer. */
|
||||
public MockRAMInputStream(MockRAMDirectory dir, String name, RAMFile f) {
|
||||
super(f);
|
||||
this.name = name;
|
||||
this.dir = dir;
|
||||
}
|
||||
|
||||
public void close() {
|
||||
super.close();
|
||||
synchronized(dir.openFiles) {
|
||||
Integer v = (Integer) dir.openFiles.get(name);
|
||||
if (v.intValue() == 1) {
|
||||
dir.openFiles.remove(name);
|
||||
} else {
|
||||
v = new Integer(v.intValue()-1);
|
||||
dir.openFiles.put(name, v);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public Object clone() {
|
||||
MockRAMInputStream clone = (MockRAMInputStream) super.clone();
|
||||
synchronized(dir.openFiles) {
|
||||
if (dir.openFiles.containsKey(name)) {
|
||||
Integer v = (Integer) dir.openFiles.get(name);
|
||||
v = new Integer(v.intValue()+1);
|
||||
dir.openFiles.put(name, v);
|
||||
} else {
|
||||
throw new RuntimeException("BUG: cloned file was not open?");
|
||||
}
|
||||
}
|
||||
return clone;
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue