Beispiel #1
0
//JAVA TO C# CONVERTER TODO TASK: Most Java annotations will not have direct .NET equivalent attributes:
//ORIGINAL LINE: @Test public void shouldOpenCleanStore() throws Exception
//JAVA TO C# CONVERTER WARNING: Method 'throws' clauses are not available in C#:
        public virtual void ShouldOpenCleanStore()
        {
            // GIVEN
            TransactionIdStore       transactionIdStore = new SimpleTransactionIdStore();
            TransactionMetadataCache positionCache      = new TransactionMetadataCache();

            LifeSupport life = new LifeSupport();
//JAVA TO C# CONVERTER WARNING: The original Java variable was marked 'final':
//ORIGINAL LINE: final org.neo4j.kernel.impl.transaction.log.files.LogFiles logFiles = org.neo4j.kernel.impl.transaction.log.files.LogFilesBuilder.builder(dir.databaseLayout(), fileSystemRule.get()).withTransactionIdStore(transactionIdStore).withLogVersionRepository(mock(LogVersionRepository.class)).build();
            LogFiles logFiles = LogFilesBuilder.builder(Dir.databaseLayout(), FileSystemRule.get()).withTransactionIdStore(transactionIdStore).withLogVersionRepository(mock(typeof(LogVersionRepository))).build();

            life.Add(logFiles);

            life.Add(new BatchingTransactionAppender(logFiles, NO_ROTATION, positionCache, transactionIdStore, BYPASS, _databaseHealth));

            try
            {
                // WHEN
                life.Start();
            }
            finally
            {
                life.Shutdown();
            }
        }
Beispiel #2
0
//JAVA TO C# CONVERTER TODO TASK: Most Java annotations will not have direct .NET equivalent attributes:
//ORIGINAL LINE: @Test public void pruningStrategyShouldBeDynamic() throws java.io.IOException
//JAVA TO C# CONVERTER WARNING: Method 'throws' clauses are not available in C#:
        public virtual void PruningStrategyShouldBeDynamic()
        {
            CheckPointer          checkPointer = GetInstanceFromDb(typeof(CheckPointer));
            Config                config       = GetInstanceFromDb(typeof(Config));
            FileSystemAbstraction fs           = GetInstanceFromDb(typeof(FileSystemAbstraction));

            LogFiles logFiles = LogFilesBuilder.builder(Db.databaseLayout(), fs).withLogVersionRepository(new SimpleLogVersionRepository()).withLastCommittedTransactionIdSupplier(() => 1).withTransactionIdStore(new SimpleTransactionIdStore()).build();

            // Force transaction log rotation
            WriteTransactionsAndRotateTwice();

            // Checkpoint to make sure strategy is evaluated
            checkPointer.ForceCheckPoint(_triggerInfo);

            // Make sure file is still there since we have disable pruning
            assertThat(CountTransactionLogs(logFiles), @is(3));

            // Change pruning to true
            config.UpdateDynamicSetting(keep_logical_logs.name(), "false", "test");

            // Checkpoint to make sure strategy is evaluated
            checkPointer.ForceCheckPoint(_triggerInfo);

            // Make sure file is removed
            assertThat(CountTransactionLogs(logFiles), @is(2));
        }
Beispiel #3
0
//JAVA TO C# CONVERTER TODO TASK: Most Java annotations will not have direct .NET equivalent attributes:
//ORIGINAL LINE: @Test public void shouldOpenAndRecoverExistingData() throws Exception
//JAVA TO C# CONVERTER WARNING: Method 'throws' clauses are not available in C#:
        public virtual void ShouldOpenAndRecoverExistingData()
        {
            // GIVEN
            TransactionIdStore       transactionIdStore = new SimpleTransactionIdStore();
            TransactionMetadataCache positionCache      = new TransactionMetadataCache();

//JAVA TO C# CONVERTER WARNING: The original Java variable was marked 'final':
//ORIGINAL LINE: final byte[] additionalHeader = new byte[]{1, 2, 5};
            sbyte[]     additionalHeader             = new sbyte[] { 1, 2, 5 };
            const int   masterId                     = 2;
            int         authorId                     = 1;
            const long  timeStarted                  = 12345;
            long        latestCommittedTxWhenStarted = 4545;
            long        timeCommitted                = timeStarted + 10;
            LifeSupport life = new LifeSupport();
//JAVA TO C# CONVERTER WARNING: The original Java variable was marked 'final':
//ORIGINAL LINE: final org.neo4j.kernel.impl.transaction.log.files.LogFiles logFiles = org.neo4j.kernel.impl.transaction.log.files.LogFilesBuilder.builder(dir.databaseLayout(), fileSystemRule.get()).withTransactionIdStore(transactionIdStore).withLogVersionRepository(mock(LogVersionRepository.class)).build();
            LogFiles logFiles = LogFilesBuilder.builder(Dir.databaseLayout(), FileSystemRule.get()).withTransactionIdStore(transactionIdStore).withLogVersionRepository(mock(typeof(LogVersionRepository))).build();

            life.Start();
            life.Add(logFiles);
            try
            {
                AddATransactionAndRewind(life, logFiles, positionCache, transactionIdStore, additionalHeader, masterId, authorId, timeStarted, latestCommittedTxWhenStarted, timeCommitted);
            }
            finally
            {
                life.Shutdown();
            }

            life = new LifeSupport();
            life.Add(logFiles);
//JAVA TO C# CONVERTER WARNING: The original Java variable was marked 'final':
//ORIGINAL LINE: final java.util.concurrent.atomic.AtomicBoolean recoveryRequired = new java.util.concurrent.atomic.AtomicBoolean();
            AtomicBoolean       recoveryRequired = new AtomicBoolean();
            FakeRecoveryVisitor visitor          = new FakeRecoveryVisitor(additionalHeader, masterId, authorId, timeStarted, timeCommitted, latestCommittedTxWhenStarted);

            LogicalTransactionStore txStore = new PhysicalLogicalTransactionStore(logFiles, positionCache, new VersionAwareLogEntryReader <ReadableClosablePositionAwareChannel>(), _monitors, true);

            life.Add(new BatchingTransactionAppender(logFiles, NO_ROTATION, positionCache, transactionIdStore, BYPASS, _databaseHealth));
            CorruptedLogsTruncator logPruner = new CorruptedLogsTruncator(_databaseDirectory, logFiles, FileSystemRule.get());

            life.add(new Recovery(new RecoveryServiceAnonymousInnerClass(this, recoveryRequired, visitor, txStore)
                                  , logPruner, new LifecycleAdapter(), mock(typeof(RecoveryMonitor)), SilentProgressReporter.INSTANCE, false));

            // WHEN
            try
            {
                life.Start();
            }
            finally
            {
                life.Shutdown();
            }

            // THEN
            assertEquals(1, visitor.VisitedTransactions);
            assertTrue(recoveryRequired.get());
        }
//JAVA TO C# CONVERTER TODO TASK: Most Java annotations will not have direct .NET equivalent attributes:
//ORIGINAL LINE: @Before public void setUp() throws java.io.IOException
//JAVA TO C# CONVERTER WARNING: Method 'throws' clauses are not available in C#:
        public virtual void SetUp()
        {
            LogVersionRepository     logVersionRepository = new SimpleLogVersionRepository();
            SimpleTransactionIdStore transactionIdStore   = new SimpleTransactionIdStore();
            LogFiles logFiles = LogFilesBuilder.builder(_directory.databaseLayout(), _fs).withLogVersionRepository(logVersionRepository).withTransactionIdStore(transactionIdStore).build();

            _life.add(logFiles);
            _logFile = logFiles.LogFile;
        }
Beispiel #5
0
//JAVA TO C# CONVERTER TODO TASK: Most Java annotations will not have direct .NET equivalent attributes:
//ORIGINAL LINE: @Before public void before() throws java.io.IOException
//JAVA TO C# CONVERTER WARNING: Method 'throws' clauses are not available in C#:
        public virtual void Before()
        {
            _lastCommittedTxId    = new AtomicLong(BASE_TX_ID);
            _logVersionRepository = new SimpleLogVersionRepository();
            _logFiles             = LogFilesBuilder.builder(_directory.databaseLayout(), _fs).withLogVersionRepository(_logVersionRepository).withTransactionIdStore(new SimpleTransactionIdStore()).build();
            _life.add(_logFiles);
            _logFile = _logFiles.LogFile;
            _writer  = _logFile.Writer;
            _transactionLogWriter = new TransactionLogWriter(new LogEntryWriter(_writer));
            _monitor = new VerifyingMonitor();
        }
        /*
         * 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 shouldKeepTransactionsIntactWhenConcurrentlyRotationAndAppending() throws Throwable
//JAVA TO C# CONVERTER WARNING: Method 'throws' clauses are not available in C#:
        public virtual void ShouldKeepTransactionsIntactWhenConcurrentlyRotationAndAppending()
        {
            // GIVEN
            LogVersionRepository logVersionRepository = new SimpleLogVersionRepository();
            LogFiles             logFiles             = LogFilesBuilder.builder(_directory.databaseLayout(), _fileSystemRule.get()).withLogVersionRepository(logVersionRepository).withRotationThreshold(ByteUnit.mebiBytes(1)).withTransactionIdStore(new SimpleTransactionIdStore()).build();

            _life.add(logFiles);
//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();
            AllTheMonitoring         monitoring    = new AllTheMonitoring(end, 100);
            TransactionIdStore       txIdStore     = new SimpleTransactionIdStore();
            TransactionMetadataCache metadataCache = new TransactionMetadataCache();

            monitoring.LogFile = logFiles.LogFile;
            DatabaseHealth health   = new DatabaseHealth(mock(typeof(DatabasePanicEventGenerator)), NullLog.Instance);
            LogRotation    rotation = new LogRotationImpl(monitoring, logFiles, health);
//JAVA TO C# CONVERTER WARNING: The original Java variable was marked 'final':
//ORIGINAL LINE: final TransactionAppender appender = life.add(new BatchingTransactionAppender(logFiles, rotation, metadataCache, txIdStore, BYPASS, health));
            TransactionAppender appender = _life.add(new BatchingTransactionAppender(logFiles, rotation, metadataCache, txIdStore, BYPASS, health));

            // WHEN
            Race race = new Race();

            for (int i = 0; i < 10; i++)
            {
                race.AddContestant(() =>
                {
                    while (!end.get())
                    {
                        try
                        {
                            appender.Append(new TransactionToApply(SillyTransaction(1_000)), NULL);
                        }
                        catch (Exception e)
                        {
                            e.printStackTrace(System.out);
                            end.set(true);
                            fail(e.Message);
                        }
                    }
                });
            }
            race.AddContestant(EndAfterMax(10, SECONDS, end));
            race.Go();

            // THEN
            assertTrue(monitoring.NumberOfRotations() > 0);
        }
Beispiel #8
0
//JAVA TO C# CONVERTER TODO TASK: Most Java annotations will not have direct .NET equivalent attributes:
//ORIGINAL LINE: @Test public void shouldExtractMetadataFromExistingTransaction() throws Exception
//JAVA TO C# CONVERTER WARNING: Method 'throws' clauses are not available in C#:
        public virtual void ShouldExtractMetadataFromExistingTransaction()
        {
            // GIVEN
            TransactionIdStore       transactionIdStore = new SimpleTransactionIdStore();
            TransactionMetadataCache positionCache      = new TransactionMetadataCache();

//JAVA TO C# CONVERTER WARNING: The original Java variable was marked 'final':
//ORIGINAL LINE: final byte[] additionalHeader = new byte[]{1, 2, 5};
            sbyte[]     additionalHeader             = new sbyte[] { 1, 2, 5 };
            const int   masterId                     = 2;
            int         authorId                     = 1;
            const long  timeStarted                  = 12345;
            long        latestCommittedTxWhenStarted = 4545;
            long        timeCommitted                = timeStarted + 10;
            LifeSupport life = new LifeSupport();
//JAVA TO C# CONVERTER WARNING: The original Java variable was marked 'final':
//ORIGINAL LINE: final org.neo4j.kernel.impl.transaction.log.files.LogFiles logFiles = org.neo4j.kernel.impl.transaction.log.files.LogFilesBuilder.builder(dir.databaseLayout(), fileSystemRule.get()).withTransactionIdStore(transactionIdStore).withLogVersionRepository(mock(LogVersionRepository.class)).build();
            LogFiles logFiles = LogFilesBuilder.builder(Dir.databaseLayout(), FileSystemRule.get()).withTransactionIdStore(transactionIdStore).withLogVersionRepository(mock(typeof(LogVersionRepository))).build();

            life.Start();
            life.Add(logFiles);
            try
            {
                AddATransactionAndRewind(life, logFiles, positionCache, transactionIdStore, additionalHeader, masterId, authorId, timeStarted, latestCommittedTxWhenStarted, timeCommitted);
            }
            finally
            {
                life.Shutdown();
            }

            life = new LifeSupport();
            life.Add(logFiles);
//JAVA TO C# CONVERTER WARNING: The original Java variable was marked 'final':
//ORIGINAL LINE: final LogicalTransactionStore store = new PhysicalLogicalTransactionStore(logFiles, positionCache, new org.neo4j.kernel.impl.transaction.log.entry.VersionAwareLogEntryReader<>(), monitors, true);
            LogicalTransactionStore store = new PhysicalLogicalTransactionStore(logFiles, positionCache, new VersionAwareLogEntryReader <ReadableClosablePositionAwareChannel>(), _monitors, true);

            // WHEN
            life.Start();
            try
            {
                VerifyTransaction(transactionIdStore, positionCache, additionalHeader, masterId, authorId, timeStarted, latestCommittedTxWhenStarted, timeCommitted, store);
            }
            finally
            {
                life.Shutdown();
            }
        }
Beispiel #9
0
//JAVA TO C# CONVERTER WARNING: Method 'throws' clauses are not available in C#:
//ORIGINAL LINE: private void addCorruptedCommandsToLastLogFile() throws java.io.IOException
        private void AddCorruptedCommandsToLastLogFile()
        {
            PositiveLogFilesBasedLogVersionRepository versionRepository = new PositiveLogFilesBasedLogVersionRepository(_logFiles);
            LogFiles internalLogFiles = LogFilesBuilder.builder(_directory.databaseLayout(), _fileSystemRule).withLogVersionRepository(versionRepository).withTransactionIdStore(new SimpleTransactionIdStore()).build();

            using (Lifespan lifespan = new Lifespan(internalLogFiles))
            {
                LogFile transactionLogFile = internalLogFiles.LogFile;

                FlushablePositionAwareChannel channel = transactionLogFile.Writer;
                TransactionLogWriter          writer  = new TransactionLogWriter(new CorruptedLogEntryWriter(channel));

                ICollection <StorageCommand> commands = new List <StorageCommand>();
                commands.Add(new Command.PropertyCommand(new PropertyRecord(1), new PropertyRecord(2)));
                commands.Add(new Command.NodeCommand(new NodeRecord(2), new NodeRecord(3)));
                PhysicalTransactionRepresentation transaction = new PhysicalTransactionRepresentation(commands);
                writer.Append(transaction, 1000);
            }
        }
Beispiel #10
0
//JAVA TO C# CONVERTER WARNING: Method 'throws' clauses are not available in C#:
//ORIGINAL LINE: TransactionLogCatchUpWriter(org.neo4j.io.layout.DatabaseLayout databaseLayout, org.neo4j.io.fs.FileSystemAbstraction fs, org.neo4j.io.pagecache.PageCache pageCache, org.neo4j.kernel.configuration.Config config, org.neo4j.logging.LogProvider logProvider, long fromTxId, boolean asPartOfStoreCopy, boolean keepTxLogsInStoreDir, boolean forceTransactionRotations) throws java.io.IOException
        internal TransactionLogCatchUpWriter(DatabaseLayout databaseLayout, FileSystemAbstraction fs, PageCache pageCache, Config config, LogProvider logProvider, long fromTxId, bool asPartOfStoreCopy, bool keepTxLogsInStoreDir, bool forceTransactionRotations)
        {
            this._pageCache                  = pageCache;
            this._log                        = logProvider.getLog(this.GetType());
            this._asPartOfStoreCopy          = asPartOfStoreCopy;
            this._rotateTransactionsManually = forceTransactionRotations;
            RecordFormats recordFormats = RecordFormatSelector.selectForStoreOrConfig(Config.defaults(), databaseLayout, fs, pageCache, logProvider);

            this._stores = (new StoreFactory(databaseLayout, config, new DefaultIdGeneratorFactory(fs), pageCache, fs, recordFormats, logProvider, EMPTY)).openNeoStores(META_DATA);
            Dependencies dependencies = new Dependencies();

            dependencies.SatisfyDependency(_stores.MetaDataStore);
            LogFilesBuilder logFilesBuilder = LogFilesBuilder.builder(databaseLayout, fs).withDependencies(dependencies).withLastCommittedTransactionIdSupplier(() => fromTxId - 1).withConfig(CustomisedConfig(config, keepTxLogsInStoreDir, forceTransactionRotations)).withLogVersionRepository(_stores.MetaDataStore);

            this._logFiles = logFilesBuilder.Build();
            this._lifespan.add(_logFiles);
            this._writer         = new TransactionLogWriter(new LogEntryWriter(_logFiles.LogFile.Writer));
            this._databaseLayout = databaseLayout;
            this._expectedTxId   = fromTxId;
        }
//JAVA TO C# CONVERTER WARNING: Method 'throws' clauses are not available in C#:
//ORIGINAL LINE: private org.neo4j.kernel.impl.transaction.log.files.LogFiles getLogFiles(org.neo4j.kernel.impl.transaction.SimpleLogVersionRepository logVersionRepository, org.neo4j.kernel.impl.transaction.SimpleTransactionIdStore transactionIdStore) throws java.io.IOException
        private LogFiles GetLogFiles(SimpleLogVersionRepository logVersionRepository, SimpleTransactionIdStore transactionIdStore)
        {
            return(LogFilesBuilder.builder(TestDirectory.databaseLayout(), FileSystem.get()).withLogVersionRepository(logVersionRepository).withTransactionIdStore(transactionIdStore).build());
        }
Beispiel #12
0
//JAVA TO C# CONVERTER TODO TASK: Most Java annotations will not have direct .NET equivalent attributes:
//ORIGINAL LINE: @Before public void setUp() throws Exception
//JAVA TO C# CONVERTER WARNING: Method 'throws' clauses are not available in C#:
        public virtual void SetUp()
        {
            _storeDir   = Directory.storeDir();
            _logFiles   = LogFilesBuilder.builder(Directory.databaseLayout(), FileSystemRule.get()).withLogVersionRepository(_logVersionRepository).withTransactionIdStore(_transactionIdStore).build();
            _schemaLife = new LifecycleAdapter();
        }
Beispiel #13
0
//JAVA TO C# CONVERTER WARNING: Method 'throws' clauses are not available in C#:
//ORIGINAL LINE: private org.neo4j.kernel.impl.transaction.log.files.LogFiles buildDefaultLogFiles() throws java.io.IOException
        private LogFiles BuildDefaultLogFiles()
        {
            return(LogFilesBuilder.builder(_directory.databaseLayout(), _fileSystemRule).withLogVersionRepository(new SimpleLogVersionRepository()).withTransactionIdStore(new SimpleTransactionIdStore()).build());
        }
//JAVA TO C# CONVERTER TODO TASK: Most Java annotations will not have direct .NET equivalent attributes:
//ORIGINAL LINE: @Test public void shouldNotSeeEmptyLogFileWhenReadingTransactionStream() throws Exception
//JAVA TO C# CONVERTER WARNING: Method 'throws' clauses are not available in C#:
        public virtual void ShouldNotSeeEmptyLogFileWhenReadingTransactionStream()
        {
            // GIVEN
            LogVersionRepository logVersionRepository = new SimpleLogVersionRepository();
            LogFiles             logFiles             = LogFilesBuilder.builder(_directory.databaseLayout(), _fileSystemRule.get()).withLogVersionRepository(logVersionRepository).withTransactionIdStore(new SimpleTransactionIdStore()).build();

            _life.add(logFiles);
            LogFile logFile = logFiles.LogFile;
            FlushablePositionAwareChannel writer        = logFile.Writer;
            LogPositionMarker             startPosition = new LogPositionMarker();

            writer.GetCurrentPosition(startPosition);

            // WHEN
            AtomicBoolean end = new AtomicBoolean();

            sbyte[] dataChunk = new sbyte[100];
            // one thread constantly writing to and rotating the channel
            AtomicInteger rotations = new AtomicInteger();

            System.Threading.CountdownEvent startSignal = new System.Threading.CountdownEvent(1);
            Future <Void> writeFuture = _t2.execute(ignored =>
            {
                ThreadLocalRandom random = ThreadLocalRandom.current();
                startSignal.Signal();
                while (!end.get())
                {
                    writer.Put(dataChunk, random.Next(1, dataChunk.Length));
                    if (logFile.RotationNeeded())
                    {
                        logFile.Rotate();
                        // Let's just close the gap to the reader so that it gets closer to the "hot zone"
                        // where the rotation happens.
                        writer.GetCurrentPosition(startPosition);
                        rotations.incrementAndGet();
                    }
                }
                return(null);
            });

            assertTrue(startSignal.await(10, SECONDS));
            // one thread reading through the channel
            long maxEndTime = currentTimeMillis() + _limitTime;
            int  reads      = 0;

            try
            {
                for ( ; currentTimeMillis() < maxEndTime && reads < LIMIT_READS && rotations.get() < LIMIT_ROTATIONS; reads++)
                {
                    using (ReadableLogChannel reader = logFile.GetReader(startPosition.NewPosition()))
                    {
                        Deplete(reader);
                    }
                }
            }
            finally
            {
                end.set(true);
                writeFuture.get();
            }

            // THEN simply getting here means this was successful
        }
//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);
            }
        }