| 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; |
| } |
| |
| } |
| |
| } |