1
package org.apache.lucene.search;
3
* Licensed to the Apache Software Foundation (ASF) under one or more
4
* contributor license agreements. See the NOTICE file distributed with
5
* this work for additional information regarding copyright ownership.
6
* The ASF licenses this file to You under the Apache License, Version 2.0
7
* (the "License"); you may not use this file except in compliance with
8
* the License. You may obtain a copy of the License at
10
* http://www.apache.org/licenses/LICENSE-2.0
12
* Unless required by applicable law or agreed to in writing, software
13
* distributed under the License is distributed on an "AS IS" BASIS,
14
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15
* See the License for the specific language governing permissions and
16
* limitations under the License.
19
import org.apache.lucene.util.LuceneTestCase;
20
import org.apache.lucene.store.Directory;
21
import org.apache.lucene.index.IndexReader;
22
import org.apache.lucene.index.IndexWriter;
23
import org.apache.lucene.index.IndexWriterConfig;
24
import org.apache.lucene.index.IndexWriterConfig.OpenMode;
25
import org.apache.lucene.analysis.MockAnalyzer;
26
import org.apache.lucene.document.*;
28
import java.util.Random;
29
import java.util.List;
30
import java.util.concurrent.atomic.AtomicBoolean;
31
import java.io.IOException;
33
public class TestThreadSafe extends LuceneTestCase {
38
class Thr extends Thread {
41
final AtomicBoolean failed;
43
// pass in random in case we want to make things reproducable
44
public Thr(int iter, Random rand, AtomicBoolean failed) {
53
for (int i=0; i<iter; i++) {
55
// pick a random index reader... a shared one, or create your own
59
switch(rand.nextInt(1)) {
60
case 0: loadDoc(ir1); break;
64
} catch (Throwable th) {
66
throw new RuntimeException(th);
71
void loadDoc(IndexReader ir) throws IOException {
72
// beware of deleted docs in the future
73
Document doc = ir.document(rand.nextInt(ir.maxDoc()),
75
public FieldSelectorResult accept(String fieldName) {
76
switch(rand.nextInt(2)) {
77
case 0: return FieldSelectorResult.LAZY_LOAD;
78
case 1: return FieldSelectorResult.LOAD;
79
// TODO: add other options
80
default: return FieldSelectorResult.LOAD;
86
List<Fieldable> fields = doc.getFields();
87
for (final Fieldable f : fields ) {
96
void validateField(Fieldable f) {
97
String val = f.stringValue();
98
if (!val.startsWith("^") || !val.endsWith("$")) {
99
throw new RuntimeException("Invalid field:" + f.toString() + " val=" +val);
103
String[] words = "now is the time for all good men to come to the aid of their country".split(" ");
105
void buildDir(Directory dir, int nDocs, int maxFields, int maxFieldLen) throws IOException {
106
IndexWriter iw = new IndexWriter(dir, new IndexWriterConfig(
107
TEST_VERSION_CURRENT, new MockAnalyzer(random)).setOpenMode(OpenMode.CREATE).setMaxBufferedDocs(10));
108
for (int j=0; j<nDocs; j++) {
109
Document d = new Document();
110
int nFields = random.nextInt(maxFields);
111
for (int i=0; i<nFields; i++) {
112
int flen = random.nextInt(maxFieldLen);
113
StringBuilder sb = new StringBuilder("^ ");
114
while (sb.length() < flen) sb.append(' ').append(words[random.nextInt(words.length)]);
116
Field.Store store = Field.Store.YES; // make random later
117
Field.Index index = Field.Index.ANALYZED; // make random later
118
d.add(newField("f"+i, sb.toString(), store, index));
126
void doTest(int iter, int nThreads) throws Exception {
127
Thr[] tarr = new Thr[nThreads];
128
AtomicBoolean failed = new AtomicBoolean();
129
for (int i=0; i<nThreads; i++) {
130
tarr[i] = new Thr(iter, new Random(random.nextLong()), failed);
133
for (int i=0; i<nThreads; i++) {
136
assertFalse(failed.get());
139
public void testLazyLoadThreadSafety() throws Exception{
140
dir1 = newDirectory();
141
// test w/ field sizes bigger than the buffer of an index input
142
buildDir(dir1, 15, 5, 2000);
144
// do many small tests so the thread locals go away inbetween
145
int num = atLeast(10);
146
for (int i = 0; i < num; i++) {
147
ir1 = IndexReader.open(dir1, false);