mirror of https://github.com/apache/lucene.git
bring back third bum: he seems to find bugs
git-svn-id: https://svn.apache.org/repos/asf/lucene/dev/trunk@1394317 13f79535-47bb-0310-9956-ffa450edef68
This commit is contained in:
parent
4a41604dca
commit
c4b9c34c39
|
@ -41,6 +41,7 @@ import org.apache.lucene.index.IndexWriterConfig;
|
||||||
import org.apache.lucene.index.NoDeletionPolicy;
|
import org.apache.lucene.index.NoDeletionPolicy;
|
||||||
import org.apache.lucene.index.SegmentInfos;
|
import org.apache.lucene.index.SegmentInfos;
|
||||||
import org.apache.lucene.util.LuceneTestCase;
|
import org.apache.lucene.util.LuceneTestCase;
|
||||||
|
import org.apache.lucene.util.ThrottledIndexOutput;
|
||||||
import org.apache.lucene.util._TestUtil;
|
import org.apache.lucene.util._TestUtil;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -76,6 +77,7 @@ public class MockDirectoryWrapper extends BaseDirectoryWrapper {
|
||||||
private Set<String> openFilesForWrite = new HashSet<String>();
|
private Set<String> openFilesForWrite = new HashSet<String>();
|
||||||
Set<String> openLocks = Collections.synchronizedSet(new HashSet<String>());
|
Set<String> openLocks = Collections.synchronizedSet(new HashSet<String>());
|
||||||
volatile boolean crashed;
|
volatile boolean crashed;
|
||||||
|
private ThrottledIndexOutput throttledOutput;
|
||||||
private Throttling throttling = Throttling.SOMETIMES;
|
private Throttling throttling = Throttling.SOMETIMES;
|
||||||
|
|
||||||
final AtomicInteger inputCloneCount = new AtomicInteger();
|
final AtomicInteger inputCloneCount = new AtomicInteger();
|
||||||
|
@ -114,16 +116,22 @@ public class MockDirectoryWrapper extends BaseDirectoryWrapper {
|
||||||
// called from different threads; else test failures may
|
// called from different threads; else test failures may
|
||||||
// not be reproducible from the original seed
|
// not be reproducible from the original seed
|
||||||
this.randomState = new Random(random.nextInt());
|
this.randomState = new Random(random.nextInt());
|
||||||
|
this.throttledOutput = new ThrottledIndexOutput(ThrottledIndexOutput
|
||||||
|
.mBitsToBytes(40 + randomState.nextInt(10)), 5 + randomState.nextInt(5), null);
|
||||||
// force wrapping of lockfactory
|
// force wrapping of lockfactory
|
||||||
this.lockFactory = new MockLockFactoryWrapper(this, delegate.getLockFactory());
|
this.lockFactory = new MockLockFactoryWrapper(this, delegate.getLockFactory());
|
||||||
|
|
||||||
// NOTE: we init rateLimiter always but we only
|
// 2% of the time use rate limiter
|
||||||
// sometimes use it (by default) in createOutput:
|
if (randomState.nextInt(50) == 17) {
|
||||||
double maxMBPerSec = 10 + 5*(randomState.nextDouble()-0.5);
|
// Use RateLimiter
|
||||||
if (LuceneTestCase.VERBOSE) {
|
double maxMBPerSec = 10 + 5*(randomState.nextDouble()-0.5);
|
||||||
System.out.println("MockDirectoryWrapper: will rate limit output IO to " + maxMBPerSec + " MB/sec");
|
if (LuceneTestCase.VERBOSE) {
|
||||||
|
System.out.println("MockDirectoryWrapper: will rate limit output IO to " + maxMBPerSec + " MB/sec");
|
||||||
|
}
|
||||||
|
rateLimiter = new RateLimiter(maxMBPerSec);
|
||||||
|
} else {
|
||||||
|
rateLimiter = null;
|
||||||
}
|
}
|
||||||
rateLimiter = new RateLimiter(maxMBPerSec);
|
|
||||||
|
|
||||||
init();
|
init();
|
||||||
}
|
}
|
||||||
|
@ -439,25 +447,22 @@ public class MockDirectoryWrapper extends BaseDirectoryWrapper {
|
||||||
ramdir.fileMap.put(name, file);
|
ramdir.fileMap.put(name, file);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
RateLimiter thisRateLimiter;
|
//System.out.println(Thread.currentThread().getName() + ": MDW: create " + name);
|
||||||
|
IndexOutput io = new MockIndexOutputWrapper(this, delegate.createOutput(name, LuceneTestCase.newIOContext(randomState, context)), name);
|
||||||
|
addFileHandle(io, name, Handle.Output);
|
||||||
|
openFilesForWrite.add(name);
|
||||||
|
|
||||||
// throttling REALLY slows down tests, so don't do it very often for SOMETIMES.
|
// throttling REALLY slows down tests, so don't do it very often for SOMETIMES.
|
||||||
if (throttling == Throttling.ALWAYS ||
|
if (throttling == Throttling.ALWAYS ||
|
||||||
(throttling == Throttling.SOMETIMES && rateLimiter == null && randomState.nextInt(50) == 0)) {
|
(throttling == Throttling.SOMETIMES && rateLimiter == null && randomState.nextInt(50) == 0)) {
|
||||||
if (LuceneTestCase.VERBOSE) {
|
if (LuceneTestCase.VERBOSE) {
|
||||||
System.out.println("MockDirectoryWrapper: throttling indexOutput");
|
System.out.println("MockDirectoryWrapper: throttling indexOutput");
|
||||||
}
|
}
|
||||||
thisRateLimiter = rateLimiter;
|
return throttledOutput.newFromDelegate(io);
|
||||||
} else {
|
} else {
|
||||||
thisRateLimiter = null;
|
return io;
|
||||||
}
|
}
|
||||||
|
|
||||||
//System.out.println(Thread.currentThread().getName() + ": MDW: create " + name);
|
|
||||||
IndexOutput io = new MockIndexOutputWrapper(this, delegate.createOutput(name, LuceneTestCase.newIOContext(randomState, context)), name, thisRateLimiter);
|
|
||||||
addFileHandle(io, name, Handle.Output);
|
|
||||||
openFilesForWrite.add(name);
|
|
||||||
return io;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private static enum Handle {
|
private static enum Handle {
|
||||||
|
|
|
@ -32,17 +32,15 @@ public class MockIndexOutputWrapper extends IndexOutput {
|
||||||
private MockDirectoryWrapper dir;
|
private MockDirectoryWrapper dir;
|
||||||
private final IndexOutput delegate;
|
private final IndexOutput delegate;
|
||||||
private boolean first=true;
|
private boolean first=true;
|
||||||
private final RateLimiter rateLimiter;
|
|
||||||
final String name;
|
final String name;
|
||||||
|
|
||||||
byte[] singleByte = new byte[1];
|
byte[] singleByte = new byte[1];
|
||||||
|
|
||||||
/** Construct an empty output buffer. */
|
/** Construct an empty output buffer. */
|
||||||
public MockIndexOutputWrapper(MockDirectoryWrapper dir, IndexOutput delegate, String name, RateLimiter rateLimiter) {
|
public MockIndexOutputWrapper(MockDirectoryWrapper dir, IndexOutput delegate, String name) {
|
||||||
this.dir = dir;
|
this.dir = dir;
|
||||||
this.name = name;
|
this.name = name;
|
||||||
this.delegate = delegate;
|
this.delegate = delegate;
|
||||||
this.rateLimiter = rateLimiter;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -80,8 +78,8 @@ public class MockIndexOutputWrapper extends IndexOutput {
|
||||||
long freeSpace = dir.maxSize == 0 ? 0 : dir.maxSize - dir.sizeInBytes();
|
long freeSpace = dir.maxSize == 0 ? 0 : dir.maxSize - dir.sizeInBytes();
|
||||||
long realUsage = 0;
|
long realUsage = 0;
|
||||||
|
|
||||||
if (rateLimiter != null && len >= 1000) {
|
if (dir.rateLimiter != null && len >= 1000) {
|
||||||
rateLimiter.pause(len);
|
dir.rateLimiter.pause(len);
|
||||||
}
|
}
|
||||||
|
|
||||||
// If MockRAMDir crashed since we were opened, then
|
// If MockRAMDir crashed since we were opened, then
|
||||||
|
|
|
@ -0,0 +1,152 @@
|
||||||
|
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.IOException;
|
||||||
|
|
||||||
|
import org.apache.lucene.store.DataInput;
|
||||||
|
import org.apache.lucene.store.IndexOutput;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Intentionally slow IndexOutput for testing.
|
||||||
|
*/
|
||||||
|
public class ThrottledIndexOutput extends IndexOutput {
|
||||||
|
public static final int DEFAULT_MIN_WRITTEN_BYTES = 1024;
|
||||||
|
private final int bytesPerSecond;
|
||||||
|
private IndexOutput delegate;
|
||||||
|
private long flushDelayMillis;
|
||||||
|
private long closeDelayMillis;
|
||||||
|
private long seekDelayMillis;
|
||||||
|
private long pendingBytes;
|
||||||
|
private long minBytesWritten;
|
||||||
|
private long timeElapsed;
|
||||||
|
private final byte[] bytes = new byte[1];
|
||||||
|
|
||||||
|
public ThrottledIndexOutput newFromDelegate(IndexOutput output) {
|
||||||
|
return new ThrottledIndexOutput(bytesPerSecond, flushDelayMillis,
|
||||||
|
closeDelayMillis, seekDelayMillis, minBytesWritten, output);
|
||||||
|
}
|
||||||
|
|
||||||
|
public ThrottledIndexOutput(int bytesPerSecond, long delayInMillis,
|
||||||
|
IndexOutput delegate) {
|
||||||
|
this(bytesPerSecond, delayInMillis, delayInMillis, delayInMillis,
|
||||||
|
DEFAULT_MIN_WRITTEN_BYTES, delegate);
|
||||||
|
}
|
||||||
|
|
||||||
|
public ThrottledIndexOutput(int bytesPerSecond, long delays,
|
||||||
|
int minBytesWritten, IndexOutput delegate) {
|
||||||
|
this(bytesPerSecond, delays, delays, delays, minBytesWritten, delegate);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static final int mBitsToBytes(int mbits) {
|
||||||
|
return mbits * 125000;
|
||||||
|
}
|
||||||
|
|
||||||
|
public ThrottledIndexOutput(int bytesPerSecond, long flushDelayMillis,
|
||||||
|
long closeDelayMillis, long seekDelayMillis, long minBytesWritten,
|
||||||
|
IndexOutput delegate) {
|
||||||
|
assert bytesPerSecond > 0;
|
||||||
|
this.delegate = delegate;
|
||||||
|
this.bytesPerSecond = bytesPerSecond;
|
||||||
|
this.flushDelayMillis = flushDelayMillis;
|
||||||
|
this.closeDelayMillis = closeDelayMillis;
|
||||||
|
this.seekDelayMillis = seekDelayMillis;
|
||||||
|
this.minBytesWritten = minBytesWritten;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void flush() throws IOException {
|
||||||
|
sleep(flushDelayMillis);
|
||||||
|
delegate.flush();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void close() throws IOException {
|
||||||
|
try {
|
||||||
|
sleep(closeDelayMillis + getDelay(true));
|
||||||
|
} finally {
|
||||||
|
delegate.close();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public long getFilePointer() {
|
||||||
|
return delegate.getFilePointer();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void seek(long pos) throws IOException {
|
||||||
|
sleep(seekDelayMillis);
|
||||||
|
delegate.seek(pos);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public long length() throws IOException {
|
||||||
|
return delegate.length();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void writeByte(byte b) throws IOException {
|
||||||
|
bytes[0] = b;
|
||||||
|
writeBytes(bytes, 0, 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void writeBytes(byte[] b, int offset, int length) throws IOException {
|
||||||
|
final long before = System.nanoTime();
|
||||||
|
delegate.writeBytes(b, offset, length);
|
||||||
|
timeElapsed += System.nanoTime() - before;
|
||||||
|
pendingBytes += length;
|
||||||
|
sleep(getDelay(false));
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
protected long getDelay(boolean closing) {
|
||||||
|
if (pendingBytes > 0 && (closing || pendingBytes > minBytesWritten)) {
|
||||||
|
long actualBps = (timeElapsed / pendingBytes) * 1000000000l; // nano to sec
|
||||||
|
if (actualBps > bytesPerSecond) {
|
||||||
|
long expected = (pendingBytes * 1000l / bytesPerSecond) ;
|
||||||
|
final long delay = expected - (timeElapsed / 1000000l) ;
|
||||||
|
pendingBytes = 0;
|
||||||
|
timeElapsed = 0;
|
||||||
|
return delay;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
private static final void sleep(long ms) {
|
||||||
|
if (ms <= 0)
|
||||||
|
return;
|
||||||
|
try {
|
||||||
|
Thread.sleep(ms);
|
||||||
|
} catch (InterruptedException e) {
|
||||||
|
throw new ThreadInterruptedException(e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void setLength(long length) throws IOException {
|
||||||
|
delegate.setLength(length);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void copyBytes(DataInput input, long numBytes) throws IOException {
|
||||||
|
delegate.copyBytes(input, numBytes);
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in New Issue