//JAVA TO C# CONVERTER TODO TASK: Most Java annotations will not have direct .NET equivalent attributes:
//ORIGINAL LINE: @Test public void shouldWaitForOngoingForceToCompleteBeforeForcingAgain() throws Throwable
//JAVA TO C# CONVERTER WARNING: Method 'throws' clauses are not available in C#:
        public virtual void ShouldWaitForOngoingForceToCompleteBeforeForcingAgain()
        {
            _channelCommandQueue.put(ChannelCommand.Dummy);

            // The 'emptyBuffer...' command will be put into the queue, and then it'll block on 'force' because the queue
            // will be at capacity.

//JAVA TO C# CONVERTER WARNING: The original Java variable was marked 'final':
//ORIGINAL LINE: final BatchingTransactionAppender appender = life.add(createTransactionAppender());
            BatchingTransactionAppender appender = _life.add(CreateTransactionAppender());

            _life.start();

            ThreadStart runnable = CreateForceAfterAppendRunnable(appender);
//JAVA TO C# CONVERTER WARNING: Java wildcard generics have no direct equivalent in .NET:
//ORIGINAL LINE: java.util.concurrent.Future<?> future = executor.submit(runnable);
            Future <object> future = _executor.submit(runnable);

            _forceSemaphore.acquire();

            Thread otherThread = fork(runnable);

            awaitThreadState(otherThread, _millisecondsToWait, Thread.State.TIMED_WAITING);

            assertThat(_channelCommandQueue.take(), @is(ChannelCommand.Dummy));
            assertThat(_channelCommandQueue.take(), @is(ChannelCommand.EmptyBufferIntoChannelAndClearIt));
            assertThat(_channelCommandQueue.take(), @is(ChannelCommand.Force));
            assertThat(_channelCommandQueue.take(), @is(ChannelCommand.EmptyBufferIntoChannelAndClearIt));
            assertThat(_channelCommandQueue.take(), @is(ChannelCommand.Force));
            future.get();
            otherThread.Join();
            assertTrue(_channelCommandQueue.Empty);
        }
//JAVA TO C# CONVERTER TODO TASK: Most Java annotations will not have direct .NET equivalent attributes:
//ORIGINAL LINE: @Test public void correctLastAppliedToPreviousLogTransactionInHeaderOnLogFileRotation() throws java.io.IOException
//JAVA TO C# CONVERTER WARNING: Method 'throws' clauses are not available in C#:
        public virtual void CorrectLastAppliedToPreviousLogTransactionInHeaderOnLogFileRotation()
        {
            LogFiles logFiles = GetLogFiles(_logVersionRepository, _transactionIdStore);

            Life.add(logFiles);
            DatabaseHealth databaseHealth = DatabaseHealth;

            LogRotationImpl                  logRotation = new LogRotationImpl(_monitors.newMonitor(typeof(Org.Neo4j.Kernel.impl.transaction.log.rotation.LogRotation_Monitor)), logFiles, databaseHealth);
            TransactionMetadataCache         transactionMetadataCache = new TransactionMetadataCache();
            SynchronizedArrayIdOrderingQueue idOrderingQueue          = new SynchronizedArrayIdOrderingQueue();

            BatchingTransactionAppender transactionAppender = new BatchingTransactionAppender(logFiles, logRotation, transactionMetadataCache, _transactionIdStore, idOrderingQueue, databaseHealth);

            Life.add(transactionAppender);

            LogAppendEvent     logAppendEvent     = new RotationLogAppendEvent(logRotation);
            TransactionToApply transactionToApply = PrepareTransaction();

            transactionAppender.Append(transactionToApply, logAppendEvent);

            assertEquals(1, logFiles.HighestLogVersion);
            File      highestLogFile = logFiles.HighestLogFile;
            LogHeader logHeader      = LogHeaderReader.readLogHeader(FileSystem, highestLogFile);

            assertEquals(2, logHeader.LastCommittedTxId);
        }
//JAVA TO C# CONVERTER TODO TASK: Most Java annotations will not have direct .NET equivalent attributes:
//ORIGINAL LINE: @Test public void shouldKernelPanicIfNotAbleToWriteACheckPoint() throws Throwable
//JAVA TO C# CONVERTER WARNING: Method 'throws' clauses are not available in C#:
        public virtual void ShouldKernelPanicIfNotAbleToWriteACheckPoint()
        {
            // Given
            IOException ioex = new IOException("boom!");
            FlushablePositionAwareChannel channel = mock(typeof(FlushablePositionAwareChannel), RETURNS_MOCKS);

            when(channel.Put(anyByte())).thenReturn(channel);
            when(channel.PutLong(anyLong())).thenThrow(ioex);
            when(channel.Put(anyByte())).thenThrow(ioex);
            when(_logFile.Writer).thenReturn(channel);
            BatchingTransactionAppender appender = Life.add(CreateTransactionAppender());

            // When
            try
            {
                appender.CheckPoint(new LogPosition(0L, 0L), LogCheckPointEvent.NULL);
                fail("should have thrown ");
            }
            catch (IOException ex)
            {
                assertEquals(ioex, ex);
            }

            // Then
            verify(_databaseHealth, times(1)).panic(ioex);
        }
        /*
         * There was an issue where if multiple concurrent appending threads did append and they moved on
         * to await a force, where the force would fail and the one doing the force would raise a panic...
         * the other threads may not notice the panic and move on to mark those transactions as committed
         * and notice the panic later (which would be too late).
         */
//JAVA TO C# CONVERTER TODO TASK: Most Java annotations will not have direct .NET equivalent attributes:
//ORIGINAL LINE: @Test public void shouldHaveAllConcurrentAppendersSeePanic() throws Throwable
//JAVA TO C# CONVERTER WARNING: Method 'throws' clauses are not available in C#:
        public virtual void ShouldHaveAllConcurrentAppendersSeePanic()
        {
            // GIVEN
            Adversary adversary = new ClassGuardedAdversary(new CountingAdversary(1, true), FailMethod(typeof(BatchingTransactionAppender), "force"));
            EphemeralFileSystemAbstraction efs = new EphemeralFileSystemAbstraction();
            FileSystemAbstraction          fs  = new AdversarialFileSystemAbstraction(adversary, efs);

            _life.add(new FileSystemLifecycleAdapter(fs));
            DatabaseHealth databaseHealth = new DatabaseHealth(mock(typeof(DatabasePanicEventGenerator)), NullLog.Instance);
            LogFiles       logFiles       = LogFilesBuilder.builder(_testDirectory.databaseLayout(), fs).withLogVersionRepository(_logVersionRepository).withTransactionIdStore(_transactionIdStore).build();

            _life.add(logFiles);
//JAVA TO C# CONVERTER WARNING: The original Java variable was marked 'final':
//ORIGINAL LINE: final BatchingTransactionAppender appender = life.add(new BatchingTransactionAppender(logFiles, logRotation, transactionMetadataCache, transactionIdStore, explicitIndexTransactionOrdering, databaseHealth));
            BatchingTransactionAppender appender = _life.add(new BatchingTransactionAppender(logFiles, _logRotation, _transactionMetadataCache, _transactionIdStore, _explicitIndexTransactionOrdering, databaseHealth));

            _life.start();

            // WHEN
            int numberOfAppenders = 10;

//JAVA TO C# CONVERTER WARNING: The original Java variable was marked 'final':
//ORIGINAL LINE: final java.util.concurrent.CountDownLatch trap = new java.util.concurrent.CountDownLatch(numberOfAppenders);
            System.Threading.CountdownEvent trap = new System.Threading.CountdownEvent(numberOfAppenders);
//JAVA TO C# CONVERTER WARNING: The original Java variable was marked 'final':
//ORIGINAL LINE: final org.neo4j.kernel.impl.transaction.tracing.LogAppendEvent beforeForceTrappingEvent = new org.neo4j.kernel.impl.transaction.tracing.LogAppendEvent_Empty()
            LogAppendEvent beforeForceTrappingEvent = new LogAppendEvent_EmptyAnonymousInnerClass(this, trap);
            Race           race = new Race();

            for (int i = 0; i < numberOfAppenders; i++)
            {
                race.AddContestant(() =>
                {
                    try
                    {
                        // Append to the log, the LogAppenderEvent will have all of the appending threads
                        // do wait for all of the other threads to start the force thing
                        appender.Append(Tx(), beforeForceTrappingEvent);
                        fail("No transaction should be considered appended");
                    }
                    catch (IOException)
                    {
                        // Good, we know that this test uses an adversarial file system which will throw
                        // an exception in BatchingTransactionAppender#force, and since all these transactions
                        // will append and be forced in the same batch, where the force will fail then
                        // all these transactions should fail. If there's any transaction not failing then
                        // it just didn't notice the panic, which would be potentially hazardous.
                    }
                });
            }

            // THEN perform the race. The relevant assertions are made inside the contestants.
            race.Go();
        }
//JAVA TO C# CONVERTER TODO TASK: Most Java annotations will not have direct .NET equivalent attributes:
//ORIGINAL LINE: @Test public void shouldForceLogChannel() throws Throwable
//JAVA TO C# CONVERTER WARNING: Method 'throws' clauses are not available in C#:
        public virtual void ShouldForceLogChannel()
        {
            BatchingTransactionAppender appender = _life.add(CreateTransactionAppender());

            _life.start();

            appender.ForceAfterAppend(_logAppendEvent);

            assertThat(_channelCommandQueue.take(), @is(ChannelCommand.EmptyBufferIntoChannelAndClearIt));
            assertThat(_channelCommandQueue.take(), @is(ChannelCommand.Force));
            assertTrue(_channelCommandQueue.Empty);
        }
//JAVA TO C# CONVERTER WARNING: 'final' parameters are ignored unless the option to convert to C# 7.2 'in' parameters is selected:
//ORIGINAL LINE: private Runnable createForceAfterAppendRunnable(final BatchingTransactionAppender appender)
        private ThreadStart CreateForceAfterAppendRunnable(BatchingTransactionAppender appender)
        {
            return(() =>
            {
                try
                {
                    appender.ForceAfterAppend(_logAppendEvent);
                }
                catch (IOException e)
                {
                    throw new Exception(e);
                }
            });
        }
//JAVA TO C# CONVERTER TODO TASK: Most Java annotations will not have direct .NET equivalent attributes:
//ORIGINAL LINE: @Test public void shouldKernelPanicIfTransactionIdsMismatch() throws Throwable
//JAVA TO C# CONVERTER WARNING: Method 'throws' clauses are not available in C#:
        public virtual void ShouldKernelPanicIfTransactionIdsMismatch()
        {
            // Given
            BatchingTransactionAppender appender = Life.add(CreateTransactionAppender());

            when(_transactionIdStore.nextCommittingTransactionId()).thenReturn(42L);
            TransactionToApply batch = new TransactionToApply(mock(typeof(TransactionRepresentation)), 43L);

            // When
            try
            {
                appender.Append(batch, Org.Neo4j.Kernel.impl.transaction.tracing.LogAppendEvent_Fields.Null);
                fail("should have thrown ");
            }
            catch (System.InvalidOperationException ex)
            {
                // Then
                verify(_databaseHealth, times(1)).panic(ex);
            }
        }
//JAVA TO C# CONVERTER TODO TASK: Most Java annotations will not have direct .NET equivalent attributes:
//ORIGINAL LINE: @Test public void shouldBeAbleToWriteACheckPoint() throws Throwable
//JAVA TO C# CONVERTER WARNING: Method 'throws' clauses are not available in C#:
        public virtual void ShouldBeAbleToWriteACheckPoint()
        {
            // Given
            FlushablePositionAwareChannel channel = mock(typeof(FlushablePositionAwareChannel), RETURNS_MOCKS);
            Flushable flushable = mock(typeof(Flushable));

            when(channel.PrepareForFlush()).thenReturn(flushable);
            when(channel.PutLong(anyLong())).thenReturn(channel);
            when(_logFile.Writer).thenReturn(channel);
            BatchingTransactionAppender appender = Life.add(CreateTransactionAppender());

            // When
            appender.CheckPoint(new LogPosition(1L, 2L), LogCheckPointEvent.NULL);

            // Then
            verify(channel, times(1)).putLong(1L);
            verify(channel, times(1)).putLong(2L);
            verify(channel, times(1)).prepareForFlush();
            verify(flushable, times(1)).flush();
            verify(_databaseHealth, never()).panic(any());
        }
//JAVA TO C# CONVERTER TODO TASK: Most Java annotations will not have direct .NET equivalent attributes:
//ORIGINAL LINE: @Test public void databasePanicShouldHandleOutOfMemoryErrors() throws java.io.IOException, InterruptedException
//JAVA TO C# CONVERTER WARNING: Method 'throws' clauses are not available in C#:
        public virtual void DatabasePanicShouldHandleOutOfMemoryErrors()
        {
//JAVA TO C# CONVERTER WARNING: The original Java variable was marked 'final':
//ORIGINAL LINE: final java.util.concurrent.CountDownLatch panicLatch = new java.util.concurrent.CountDownLatch(1);
            System.Threading.CountdownEvent panicLatch = new System.Threading.CountdownEvent(1);
//JAVA TO C# CONVERTER WARNING: The original Java variable was marked 'final':
//ORIGINAL LINE: final java.util.concurrent.CountDownLatch adversaryLatch = new java.util.concurrent.CountDownLatch(1);
            System.Threading.CountdownEvent adversaryLatch = new System.Threading.CountdownEvent(1);
            OutOfMemoryAwareFileSystem      fs             = new OutOfMemoryAwareFileSystem();

            _life.add(new FileSystemLifecycleAdapter(fs));
            DatabaseHealth slowPanicDatabaseHealth = new SlowPanickingDatabaseHealth(panicLatch, adversaryLatch);
            LogFiles       logFiles = LogFilesBuilder.builder(_testDirectory.databaseLayout(), fs).withLogVersionRepository(_logVersionRepository).withTransactionIdStore(_transactionIdStore).build();

            _life.add(logFiles);
//JAVA TO C# CONVERTER WARNING: The original Java variable was marked 'final':
//ORIGINAL LINE: final BatchingTransactionAppender appender = life.add(new BatchingTransactionAppender(logFiles, logRotation, transactionMetadataCache, transactionIdStore, explicitIndexTransactionOrdering, slowPanicDatabaseHealth));
            BatchingTransactionAppender appender = _life.add(new BatchingTransactionAppender(logFiles, _logRotation, _transactionMetadataCache, _transactionIdStore, _explicitIndexTransactionOrdering, slowPanicDatabaseHealth));

            _life.start();

            // Commit initial transaction
            appender.Append(Tx(), Org.Neo4j.Kernel.impl.transaction.tracing.LogAppendEvent_Fields.Null);

            // Try to commit one transaction, will fail during flush with OOM, but not actually panic
            fs.ShouldOOM = true;
            Future <long> failingTransaction = _executor.submit(() => appender.Append(Tx(), Org.Neo4j.Kernel.impl.transaction.tracing.LogAppendEvent_Fields.Null));

            panicLatch.await();

            // Try to commit one additional transaction, should fail since database has already panicked
            fs.ShouldOOM = false;
            try
            {
                appender.Append(Tx(), new LogAppendEvent_EmptyAnonymousInnerClass2(this, adversaryLatch));
                fail("Should have failed since database should have panicked");
            }
            catch (IOException e)
            {
                assertTrue(e.Message.contains("The database has encountered a critical error"));
            }

            // Check that we actually got an OutOfMemoryError
            try
            {
                failingTransaction.get();
                fail("Should have failed with OutOfMemoryError error");
            }
            catch (ExecutionException e)
            {
                assertTrue(e.InnerException is System.OutOfMemoryException);
            }

            // Check number of transactions, should only have one
            LogEntryReader <ReadableClosablePositionAwareChannel> logEntryReader = new VersionAwareLogEntryReader <ReadableClosablePositionAwareChannel>();

            assertEquals(logFiles.LowestLogVersion, logFiles.HighestLogVersion);
            long version = logFiles.HighestLogVersion;

            using (LogVersionedStoreChannel channel = logFiles.OpenForVersion(version), ReadAheadLogChannel readAheadLogChannel = new ReadAheadLogChannel(channel), LogEntryCursor cursor = new LogEntryCursor(logEntryReader, readAheadLogChannel))
            {
                LogEntry entry;
                long     numberOfTransactions = 0;
                while (cursor.Next())
                {
                    entry = cursor.Get();
                    if (entry is LogEntryCommit)
                    {
                        numberOfTransactions++;
                    }
                }
                assertEquals(1, numberOfTransactions);
            }
        }