private ThreadStart Inserter <T1>(AtomicReferenceArray <T1> lastBatches, Generator[] generators, System.Threading.CountdownEvent insertersDone, ReadWriteLock updateLock, int slot) where T1 : Org.Neo4j.Kernel.Api.Index.IndexEntryUpdate <T1> { int worstCaseEntriesPerThread = BATCHES_PER_THREAD * MAX_BATCH_SIZE; return(throwing(() => { try { Generator generator = generators[slot] = new Generator(this, MAX_BATCH_SIZE, Random.seed() + slot, slot * worstCaseEntriesPerThread); for (int j = 0; j < BATCHES_PER_THREAD; j++) { IList <IndexEntryUpdate <object> > batch = generator.Batch(); updateLock.readLock().@lock(); try { _populator.add(batch); } finally { updateLock.readLock().unlock(); } lastBatches.set(slot, batch); } } finally { // This helps the updater know when to stop updating insertersDone.Signal(); } })); }
public void run() { if (random.nextFloat() < CHANCE_LARGE_TX) { // Few large transactions using (Transaction tx = _outerInstance.db.beginTx()) { for (int i = 0; i < LARGE_TX_SIZE; i++) { // Nodes are created with properties here. Whereas the properties don't have a functional // impact on this test they do affect timings so that the issue is (was) triggered more often // and therefore have a positive effect on this test. _outerInstance.db.createNode(randomLabels()).setProperty("name", randomUUID().ToString()); } tx.Success(); } } else { // Many small create/delete transactions Node node; using (Transaction tx = _outerInstance.db.beginTx()) { node = _outerInstance.db.createNode(randomLabels()); _nodeHeads.set(_guy, node); tx.Success(); } if (random.nextFloat() < CHANCE_TO_DELETE_BY_SAME_THREAD) { // Most of the time delete in this thread if (_nodeHeads.getAndSet(_guy, null) != null) { using (Transaction tx = _outerInstance.db.beginTx()) { node.Delete(); tx.Success(); } } // Otherwise there will be other threads sitting there waiting for these nodes and deletes them if they can } } }
//JAVA TO C# CONVERTER TODO TASK: Most Java annotations will not have direct .NET equivalent attributes: //ORIGINAL LINE: @Test public void shouldBeAbleToSnapshotDuringHeavyLoad() throws Throwable //JAVA TO C# CONVERTER WARNING: Method 'throws' clauses are not available in C#: public virtual void ShouldBeAbleToSnapshotDuringHeavyLoad() { // GIVEN //JAVA TO C# CONVERTER WARNING: The original Java variable was marked 'final': //ORIGINAL LINE: final KernelTransactions transactions = newKernelTransactions(); KernelTransactions transactions = NewKernelTransactions(); Race race = new Race(); const int threads = 50; //JAVA TO C# CONVERTER WARNING: The original Java variable was marked 'final': //ORIGINAL LINE: final java.util.concurrent.atomic.AtomicBoolean end = new java.util.concurrent.atomic.AtomicBoolean(); AtomicBoolean end = new AtomicBoolean(); //JAVA TO C# CONVERTER WARNING: The original Java variable was marked 'final': //ORIGINAL LINE: final java.util.concurrent.atomic.AtomicReferenceArray<KernelTransactionsSnapshot> snapshots = new java.util.concurrent.atomic.AtomicReferenceArray<>(threads); AtomicReferenceArray <KernelTransactionsSnapshot> snapshots = new AtomicReferenceArray <KernelTransactionsSnapshot>(threads); // Representing "transaction" threads for (int i = 0; i < threads; i++) { //JAVA TO C# CONVERTER WARNING: The original Java variable was marked 'final': //ORIGINAL LINE: final int threadIndex = i; int threadIndex = i; race.AddContestant(() => { ThreadLocalRandom random = ThreadLocalRandom.current(); while (!end.get()) { try { using (KernelTransaction transaction = GetKernelTransaction(transactions)) { KernelTransactionsSnapshot snapshot = null; try { parkNanos(MILLISECONDS.toNanos(random.Next(3))); if (snapshots.get(threadIndex) == null) { requireNonNull(transactions, "transactions is null"); snapshot = requireNonNull(transactions.Get(), "transactions.get() returned null"); snapshots.set(threadIndex, snapshot); parkNanos(MILLISECONDS.toNanos(random.Next(3))); } } catch (Exception e) { StringBuilder sb = (new StringBuilder("Gotcha!\n")).Append("threadIndex=").Append(threadIndex).Append('\n').Append("transaction=").Append(transaction).Append('\n').Append("snapshots=").Append(snapshots).Append('\n').Append("snapshot=").Append(snapshot).Append('\n').Append("end=").Append(end); throw new Exception(sb.ToString(), e); } } } catch (TransactionFailureException e) { throw new Exception(e); } } }); } // Just checks snapshots race.AddContestant(() => { ThreadLocalRandom random = ThreadLocalRandom.current(); int snapshotsLeft = 1_000; while (snapshotsLeft > 0) { int threadIndex = random.Next(threads); KernelTransactionsSnapshot snapshot = snapshots.get(threadIndex); if (snapshot != null && snapshot.AllClosed()) { snapshotsLeft--; snapshots.set(threadIndex, null); } } // End condition of this test can be described as: // when 1000 snapshots have been seen as closed. // setting this boolean to true will have all other threads end as well so that race.go() will end end.set(true); }); // WHEN race.Go(); }