public void TestConcurrentAccess() { assertEquals(1, searchers.Count); using IndexReader r = DirectoryReader.Open(userindex); spellChecker.ClearIndex(); assertEquals(2, searchers.Count); Addwords(r, spellChecker, "field1"); assertEquals(3, searchers.Count); int num_field1 = this.NumDoc(); Addwords(r, spellChecker, "field2"); assertEquals(4, searchers.Count); int num_field2 = this.NumDoc(); assertEquals(num_field2, num_field1 + 1); int numThreads = 5 + Random.nextInt(5); SpellCheckWorker[] workers = new SpellCheckWorker[numThreads]; var stop = new AtomicBoolean(false); for (int i = 0; i < numThreads; i++) { SpellCheckWorker spellCheckWorker = new SpellCheckWorker(this, r, stop); workers[i] = spellCheckWorker; spellCheckWorker.Start(); } int iterations = 5 + Random.nextInt(5); for (int i = 0; i < iterations; i++) { Thread.Sleep(100); // concurrently reset the spell index spellChecker.SetSpellIndex(this.spellindex); // for debug - prints the internal open searchers // showSearchersOpen(); } spellChecker.Dispose(); stop.Value = true; // wait for 60 seconds - usually this is very fast but coverage runs could take quite long //executor.awaitTermination(60L, TimeUnit.SECONDS); foreach (SpellCheckWorker worker in workers) { worker.Join((long)TimeSpan.FromSeconds(60).TotalMilliseconds); } for (int i = 0; i < workers.Length; i++) { assertFalse(string.Format(CultureInfo.InvariantCulture, "worker thread {0} failed \n" + workers[i].Error, i), workers[i].Error != null); assertTrue(string.Format(CultureInfo.InvariantCulture, "worker thread {0} is still running but should be terminated", i), workers[i].terminated); } // 4 searchers more than iterations // 1. at creation // 2. clearIndex() // 2. and 3. during addwords assertEquals(iterations + 4, searchers.Count); AssertSearchersClosed(); }
public void TestConcurrentAccess() { Assert.AreEqual(1, searchers.Count); IndexReader r = IndexReader.Open(userindex, true); spellChecker.ClearIndex(); Assert.AreEqual(2, searchers.Count); Addwords(r, "field1"); Assert.AreEqual(3, searchers.Count); int num_field1 = this.Numdoc(); Addwords(r, "field2"); Assert.AreEqual(4, searchers.Count); int num_field2 = this.Numdoc(); Assert.AreEqual(num_field2, num_field1 + 1); int numThreads = 5 + this.random.Next(5); SpellCheckWorker[] workers = new SpellCheckWorker[numThreads]; for (int i = 0; i < numThreads; i++) { SpellCheckWorker spellCheckWorker = new SpellCheckWorker(r, this); spellCheckWorker.start(); workers[i] = spellCheckWorker; } int iterations = 5 + random.Next(5); for (int i = 0; i < iterations; i++) { Thread.Sleep(100); // concurrently reset the spell index spellChecker.SetSpellIndex(this.spellindex); // for debug - prints the internal Open searchers // showSearchersOpen(); } spellChecker.Close(); joinAll(workers, 5000); for (int i = 0; i < workers.Length; i++) { Assert.False(workers[i].failed); Assert.True(workers[i].terminated); } // 4 searchers more than iterations // 1. at creation // 2. ClearIndex() // 2. and 3. during Addwords Assert.AreEqual(iterations + 4, searchers.Count); AssertSearchersClosed(); }
private void joinAll(SpellCheckWorker[] workers, long timeout) { for (int j = 0; j < workers.Length; j++) { long time = (long)DateTime.Now.TimeOfDay.TotalMilliseconds; if (timeout < 0) { // this could be helpful if it Assert.Fails one day Console.WriteLine("Warning: " + (workers.Length - j) + " threads have not joined but joinall timed out"); break; } workers[j].join(timeout); timeout -= (long)DateTime.Now.TimeOfDay.TotalMilliseconds - time; } }
public void TestConcurrentAccess() { assertEquals(1, searchers.Count); using (IndexReader r = DirectoryReader.Open(userindex)) { spellChecker.ClearIndex(); assertEquals(2, searchers.Count); Addwords(r, spellChecker, "field1"); assertEquals(3, searchers.Count); int num_field1 = this.NumDoc(); Addwords(r, spellChecker, "field2"); assertEquals(4, searchers.Count); int num_field2 = this.NumDoc(); assertEquals(num_field2, num_field1 + 1); int numThreads = 5 + Random().nextInt(5); SpellCheckWorker[] workers = new SpellCheckWorker[numThreads]; var stop = new AtomicBoolean(false); for (int i = 0; i < numThreads; i++) { SpellCheckWorker spellCheckWorker = new SpellCheckWorker(this, r, stop); workers[i] = spellCheckWorker; spellCheckWorker.Start(); } int iterations = 5 + Random().nextInt(5); for (int i = 0; i < iterations; i++) { Thread.Sleep(100); // concurrently reset the spell index spellChecker.SpellIndex = (this.spellindex); // for debug - prints the internal open searchers // showSearchersOpen(); } spellChecker.Dispose(); stop.Set(true); // wait for 60 seconds - usually this is very fast but coverage runs could take quite long //executor.awaitTermination(60L, TimeUnit.SECONDS); foreach (SpellCheckWorker worker in workers) { worker.Join((long)TimeSpan.FromSeconds(60).TotalMilliseconds); } for (int i = 0; i < workers.Length; i++) { assertFalse(string.Format(CultureInfo.InvariantCulture, "worker thread {0} failed \n" + workers[i].Error, i), workers[i].Error != null); assertTrue(string.Format(CultureInfo.InvariantCulture, "worker thread {0} is still running but should be terminated", i), workers[i].terminated); } // 4 searchers more than iterations // 1. at creation // 2. clearIndex() // 2. and 3. during addwords assertEquals(iterations + 4, searchers.Count); AssertSearchersClosed(); } }
public async Task TestConcurrentAccess() { assertEquals(1, searchers.Count); using IndexReader r = DirectoryReader.Open(userindex); spellChecker.ClearIndex(); assertEquals(2, searchers.Count); Addwords(r, spellChecker, "field1"); assertEquals(3, searchers.Count); int num_field1 = this.NumDoc(); Addwords(r, spellChecker, "field2"); assertEquals(4, searchers.Count); int num_field2 = this.NumDoc(); assertEquals(num_field2, num_field1 + 1); int numThreads = 5 + Random.nextInt(5); var tasks = new ConcurrentBag <Task>(); SpellCheckWorker[] workers = new SpellCheckWorker[numThreads]; var executor = new LimitedConcurrencyLevelTaskScheduler(numThreads); // LUCENENET NOTE: Not sure why in Java they decided to pass the max concurrent threads as all of the threads, but this demonstrates how to use a custom TaskScheduler in .NET. using var shutdown = new CancellationTokenSource(); var cancellationToken = shutdown.Token; var stop = new AtomicBoolean(false); var taskFactory = new TaskFactory(executor); for (int i = 0; i < numThreads; i++) { SpellCheckWorker spellCheckWorker = new SpellCheckWorker(this, r, stop, cancellationToken, taskNum: i); workers[i] = spellCheckWorker; tasks.Add(taskFactory.StartNew(() => spellCheckWorker.Run(), cancellationToken)); } int iterations = 5 + Random.nextInt(5); for (int i = 0; i < iterations; i++) { Thread.Sleep(100); // concurrently reset the spell index spellChecker.SetSpellIndex(this.spellindex); // for debug - prints the internal open searchers // showSearchersOpen(); } stop.Value = true; executor.Shutdown(); // Stop allowing tasks to queue try { // wait for 60 seconds - usually this is very fast but coverage runs could take quite long shutdown.CancelAfter(TimeSpan.FromSeconds(60)); await Task.WhenAll(tasks.ToArray()); } catch (OperationCanceledException) { if (Verbose) { Console.WriteLine($"\n{nameof(OperationCanceledException)} thrown\n(safe shutdown after timeout)"); } } finally { shutdown.Dispose(); spellChecker.Dispose(); // In Lucene, this was the line that did "stop" and the running task responded to the AlreadyClosedException to break out of the loop, but we are using AtomicBoolean to signal instead. } for (int i = 0; i < workers.Length; i++) { assertFalse(string.Format(CultureInfo.InvariantCulture, "worker thread {0} failed \n" + workers[i].Error, i), workers[i].Error != null); assertTrue(string.Format(CultureInfo.InvariantCulture, "worker thread {0} is still running but should be terminated", i), workers[i].terminated); } // 4 searchers more than iterations // 1. at creation // 2. clearIndex() // 2. and 3. during addwords assertEquals(iterations + 4, searchers.Count); AssertSearchersClosed(); }