fix several threading issues

git-svn-id: https://svn.apache.org/repos/asf/lucene/java/trunk@328151 13f79535-47bb-0310-9956-ffa450edef68
This commit is contained in:
Daniel Naber 2005-10-24 20:54:45 +00:00
parent 8559a28c6e
commit 0c26106b36
1 changed files with 82 additions and 70 deletions

View File

@ -18,6 +18,7 @@ package org.apache.lucene.index;
import java.io.File; import java.io.File;
import java.io.IOException; import java.io.IOException;
import java.util.EmptyStackException;
import java.util.Random; import java.util.Random;
import java.util.Stack; import java.util.Stack;
@ -33,15 +34,13 @@ import org.apache.lucene.store.FSDirectory;
import org.apache.lucene.store.RAMDirectory; import org.apache.lucene.store.RAMDirectory;
/** /**
* Tests for the "Index" class, including accesses from two threads at the * Tests for the "IndexModifier" class, including accesses from two threads at the
* same time. * same time.
* *
* @author Daniel Naber * @author Daniel Naber
*/ */
public class TestIndexModifier extends TestCase { public class TestIndexModifier extends TestCase {
private final int ITERATIONS = 500; // iterations of thread test
private int docCount = 0; private int docCount = 0;
private final Term allDocTerm = new Term("all", "x"); private final Term allDocTerm = new Term("all", "x");
@ -138,7 +137,7 @@ public class TestIndexModifier extends TestCase {
} }
private void testIndexInternal(int maxWait) throws IOException { private void testIndexInternal(int maxWait) throws IOException {
boolean create = true; final boolean create = true;
//Directory rd = new RAMDirectory(); //Directory rd = new RAMDirectory();
// work on disk to make sure potential lock problems are tested: // work on disk to make sure potential lock problems are tested:
String tempDir = System.getProperty("java.io.tmpdir"); String tempDir = System.getProperty("java.io.tmpdir");
@ -146,16 +145,18 @@ public class TestIndexModifier extends TestCase {
throw new IOException("java.io.tmpdir undefined, cannot run test"); throw new IOException("java.io.tmpdir undefined, cannot run test");
File indexDir = new File(tempDir, "lucenetestindex"); File indexDir = new File(tempDir, "lucenetestindex");
Directory rd = FSDirectory.getDirectory(indexDir, create); Directory rd = FSDirectory.getDirectory(indexDir, create);
IndexThread.id = 0;
IndexThread.idStack.clear();
IndexModifier index = new IndexModifier(rd, new StandardAnalyzer(), create); IndexModifier index = new IndexModifier(rd, new StandardAnalyzer(), create);
IndexThread thread1 = new IndexThread(index, maxWait); IndexThread thread1 = new IndexThread(index, maxWait, 1);
thread1.start(); thread1.start();
IndexThread thread2 = new IndexThread(index, maxWait); IndexThread thread2 = new IndexThread(index, maxWait, 2);
thread2.start(); thread2.start();
while(thread1.isAlive() || thread2.isAlive()) { while(thread1.isAlive() || thread2.isAlive()) {
try { try {
Thread.sleep(100); Thread.sleep(100);
} catch (InterruptedException e) { } catch (InterruptedException e) {
e.printStackTrace(); throw new RuntimeException(e);
} }
} }
index.optimize(); index.optimize();
@ -181,12 +182,6 @@ public class TestIndexModifier extends TestCase {
dir.delete(); dir.delete();
} }
private int id = 0;
private Stack idStack = new Stack();
// TODO: test case is not reproducible despite pseudo-random numbers
// used for anything:
private Random random = new Random(101); // constant seed for reproducability
private class PowerIndex extends IndexModifier { private class PowerIndex extends IndexModifier {
public PowerIndex(Directory dir, Analyzer analyzer, boolean create) throws IOException { public PowerIndex(Directory dir, Analyzer analyzer, boolean create) throws IOException {
super(dir, analyzer, create); super(dir, analyzer, create);
@ -200,18 +195,29 @@ public class TestIndexModifier extends TestCase {
} }
} }
private class IndexThread extends Thread { }
class IndexThread extends Thread {
private final static int ITERATIONS = 500; // iterations of thread test
static int id = 0;
static Stack idStack = new Stack();
int added = 0;
int deleted = 0;
private int maxWait = 10; private int maxWait = 10;
private IndexModifier index; private IndexModifier index;
private int added = 0; private int threadNumber;
private int deleted = 0; private Random random;
IndexThread(IndexModifier index, int maxWait) { IndexThread(IndexModifier index, int maxWait, int threadNumber) {
this.index = index; this.index = index;
this.maxWait = maxWait; this.maxWait = maxWait;
id = 0; this.threadNumber = threadNumber;
idStack.clear(); // TODO: test case is not reproducible despite pseudo-random numbers:
random = new Random(101+threadNumber); // constant seed for better reproducability
} }
public void run() { public void run() {
@ -222,21 +228,25 @@ public class TestIndexModifier extends TestCase {
index.optimize(); index.optimize();
} else if (rand < 60) { } else if (rand < 60) {
Document doc = getDocument(); Document doc = getDocument();
//System.out.println("add doc id=" + doc.get("id"));
index.addDocument(doc); index.addDocument(doc);
idStack.push(doc.get("id")); idStack.push(doc.get("id"));
added++; added++;
} else {
if (idStack.size() == 0) {
// not enough docs in index, let's wait for next chance
} else { } else {
// we just delete the last document added and remove it // we just delete the last document added and remove it
// from the id stack so that it won't be removed twice: // from the id stack so that it won't be removed twice:
String delId = (String)idStack.pop(); String delId = null;
//System.out.println("delete doc id = " + delId); try {
index.delete(new Term("id", new Integer(delId).toString())); delId = (String)idStack.pop();
deleted++; } catch (EmptyStackException e) {
continue;
} }
Term delTerm = new Term("id", new Integer(delId).toString());
int delCount = index.delete(delTerm);
if (delCount != 1) {
throw new RuntimeException("Internal error: " + threadNumber + " deleted " + delCount +
" documents, term=" + delTerm);
}
deleted++;
} }
if (maxWait > 0) { if (maxWait > 0) {
try { try {
@ -244,7 +254,7 @@ public class TestIndexModifier extends TestCase {
//System.out.println("waiting " + rand + "ms"); //System.out.println("waiting " + rand + "ms");
Thread.sleep(rand); Thread.sleep(rand);
} catch (InterruptedException e) { } catch (InterruptedException e) {
e.printStackTrace(); throw new RuntimeException(e);
} }
} }
} }
@ -255,8 +265,11 @@ public class TestIndexModifier extends TestCase {
private Document getDocument() { private Document getDocument() {
Document doc = new Document(); Document doc = new Document();
doc.add(new Field("id", new Integer(id++).toString(), Field.Store.YES, synchronized (getClass()) {
doc.add(new Field("id", new Integer(id).toString(), Field.Store.YES,
Field.Index.UN_TOKENIZED)); Field.Index.UN_TOKENIZED));
id++;
}
// add random stuff: // add random stuff:
doc.add(new Field("content", new Integer(random.nextInt(1000)).toString(), Field.Store.YES, doc.add(new Field("content", new Integer(random.nextInt(1000)).toString(), Field.Store.YES,
Field.Index.TOKENIZED)); Field.Index.TOKENIZED));
@ -265,6 +278,5 @@ public class TestIndexModifier extends TestCase {
doc.add(new Field("all", "x", Field.Store.YES, Field.Index.TOKENIZED)); doc.add(new Field("all", "x", Field.Store.YES, Field.Index.TOKENIZED));
return doc; return doc;
} }
}
} }