blob: b9631eec6e65c49c504f4e5cef790af93b07a0af [file] [log] [blame]
using System;
using System.Threading;
using Lucene.Net.Randomized.Generators;
namespace Lucene.Net.Facet
{
/*
* 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.
*/
using IOContext = Lucene.Net.Store.IOContext;
using IndexInput = Lucene.Net.Store.IndexInput;
using IndexOutput = Lucene.Net.Store.IndexOutput;
using RAMDirectory = Lucene.Net.Store.RAMDirectory;
/// <summary>
/// Test utility - slow directory
/// </summary>
// TODO: move to test-framework and sometimes use in tests?
public class SlowRAMDirectory : RAMDirectory
{
private const int IO_SLEEP_THRESHOLD = 50;
internal Random random;
private int sleepMillis;
public virtual int SleepMillis
{
set => this.sleepMillis = value;
}
public SlowRAMDirectory(int sleepMillis, Random random)
{
this.sleepMillis = sleepMillis;
this.random = random;
}
public override IndexOutput CreateOutput(string name, IOContext context)
{
if (sleepMillis != -1)
{
return new SlowIndexOutput(this, base.CreateOutput(name, context));
}
return base.CreateOutput(name, context);
}
public override IndexInput OpenInput(string name, IOContext context)
{
if (sleepMillis != -1)
{
return new SlowIndexInput(this, base.OpenInput(name, context));
}
return base.OpenInput(name, context);
}
internal virtual void doSleep(Random random, int length)
{
int sTime = length < 10 ? sleepMillis : (int)(sleepMillis * Math.Log(length));
if (random != null)
{
sTime = random.Next(sTime);
}
//#if FEATURE_THREAD_INTERRUPT
// try
// {
//#endif
Thread.Sleep(sTime);
//#if FEATURE_THREAD_INTERRUPT
// }
// catch (ThreadInterruptedException e) // LUCENENET NOTE: Senseless to catch and rethrow the same exception type
// {
// throw new ThreadInterruptedException("Thread Interrupted Exception", e);
// }
//#endif
}
/// <summary>
/// Make a private random. </summary>
internal virtual Random forkRandom()
{
if (random == null)
{
return null;
}
return new Random((int)random.NextInt64());
}
/// <summary>
/// Delegate class to wrap an IndexInput and delay reading bytes by some
/// specified time.
/// </summary>
private class SlowIndexInput : IndexInput
{
private readonly SlowRAMDirectory outerInstance;
internal IndexInput ii;
internal int numRead = 0;
internal Random rand;
public SlowIndexInput(SlowRAMDirectory outerInstance, IndexInput ii)
: base("SlowIndexInput(" + ii + ")")
{
this.outerInstance = outerInstance;
this.rand = outerInstance.forkRandom();
this.ii = ii;
}
public override byte ReadByte()
{
if (numRead >= IO_SLEEP_THRESHOLD)
{
outerInstance.doSleep(rand, 0);
numRead = 0;
}
++numRead;
return ii.ReadByte();
}
public override void ReadBytes(byte[] b, int offset, int len)
{
if (numRead >= IO_SLEEP_THRESHOLD)
{
outerInstance.doSleep(rand, len);
numRead = 0;
}
numRead += len;
ii.ReadBytes(b, offset, len);
}
// TODO: is it intentional that clone doesnt wrap?
public override object Clone()
{
return ii.Clone();
}
protected override void Dispose(bool disposing)
{
if (disposing)
{
ii.Dispose();
}
}
public override bool Equals(object o)
{
return ii.Equals(o);
}
public override long GetFilePointer()
{
return ii.GetFilePointer();
}
public override void Seek(long pos)
{
ii.Seek(pos);
}
public override int GetHashCode()
{
return ii.GetHashCode();
}
public override long Length => ii.Length;
}
/// <summary>
/// Delegate class to wrap an IndexOutput and delay writing bytes by some
/// specified time.
/// </summary>
private class SlowIndexOutput : IndexOutput
{
private readonly SlowRAMDirectory outerInstance;
internal IndexOutput io;
internal int numWrote;
internal readonly Random rand;
public SlowIndexOutput(SlowRAMDirectory outerInstance, IndexOutput io)
{
this.outerInstance = outerInstance;
this.io = io;
this.rand = outerInstance.forkRandom();
}
public override void WriteByte(byte b)
{
if (numWrote >= IO_SLEEP_THRESHOLD)
{
outerInstance.doSleep(rand, 0);
numWrote = 0;
}
++numWrote;
io.WriteByte(b);
}
public override void WriteBytes(byte[] b, int offset, int length)
{
if (numWrote >= IO_SLEEP_THRESHOLD)
{
outerInstance.doSleep(rand, length);
numWrote = 0;
}
numWrote += length;
io.WriteBytes(b, offset, length);
}
protected override void Dispose(bool disposing)
{
if (disposing)
{
io.Dispose();
}
}
public override void Flush()
{
io.Flush();
}
public override long GetFilePointer()
{
return io.GetFilePointer();
}
[Obsolete]
public override void Seek(long pos)
{
io.Seek(pos);
}
public override long Checksum => io.Checksum;
}
}
}