Beispiel #1
0
        private static void AssertTransaction(LogEntry[] transactionEntries, long expectedId)
        {
            assertTrue(Arrays.ToString(transactionEntries), transactionEntries[0] is LogEntryStart);
            assertTrue(transactionEntries[1] is LogEntryCommand);
            LogEntryCommand command = transactionEntries[1].As();

            assertEquals(expectedId, ((Command.NodeCommand)command.Command).Key);
            assertTrue(transactionEntries[2] is LogEntryCommit);
            LogEntryCommit commit = transactionEntries[2].As();

            assertEquals(expectedId, commit.TxId);
        }
Beispiel #2
0
        private CommittedTransactionRepresentation CreateTxWithId(long txId)
        {
            CommittedTransactionRepresentation tx = mock(typeof(CommittedTransactionRepresentation));
            LogEntryCommit commitEntry            = mock(typeof(LogEntryCommit));

            when(commitEntry.TxId).thenReturn(txId);
            TransactionRepresentation txRep = mock(typeof(TransactionRepresentation));

            sbyte[] encodedRaftLogIndex = encodeLogIndexAsTxHeader(txId - 5);                 // just some arbitrary offset
            when(txRep.AdditionalHeader()).thenReturn(encodedRaftLogIndex);
            when(tx.TransactionRepresentation).thenReturn(txRep);
            when(tx.CommitEntry).thenReturn(commitEntry);
            return(tx);
        }
//JAVA TO C# CONVERTER TODO TASK: Most Java annotations will not have direct .NET equivalent attributes:
//ORIGINAL LINE: @Test public void shouldAppendCommittedTransactions() throws Exception
//JAVA TO C# CONVERTER WARNING: Method 'throws' clauses are not available in C#:
        public virtual void ShouldAppendCommittedTransactions()
        {
            // GIVEN
            when(_logFile.Writer).thenReturn(_channel);
            long nextTxId = 15;

            when(_transactionIdStore.nextCommittingTransactionId()).thenReturn(nextTxId);
            TransactionAppender appender = Life.add(new BatchingTransactionAppender(_logFiles, NO_ROTATION, _positionCache, _transactionIdStore, BYPASS, _databaseHealth));

            // WHEN
//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 = nextTxId - 5;
            long       timeCommitted                = timeStarted + 10;
            PhysicalTransactionRepresentation transactionRepresentation = new PhysicalTransactionRepresentation(SingleCreateNodeCommand(0));

            transactionRepresentation.SetHeader(additionalHeader, masterId, authorId, timeStarted, latestCommittedTxWhenStarted, timeCommitted, -1);

            LogEntryStart  start  = new LogEntryStart(0, 0, 0L, latestCommittedTxWhenStarted, null, LogPosition.UNSPECIFIED);
            LogEntryCommit commit = new LogEntryCommit(nextTxId, 0L);
            CommittedTransactionRepresentation transaction = new CommittedTransactionRepresentation(start, transactionRepresentation, commit);

            appender.Append(new TransactionToApply(transactionRepresentation, transaction.CommitEntry.TxId), _logAppendEvent);

            // THEN
            LogEntryReader <ReadableLogChannel> logEntryReader = new VersionAwareLogEntryReader <ReadableLogChannel>();

            using (PhysicalTransactionCursor <ReadableLogChannel> reader = new PhysicalTransactionCursor <ReadableLogChannel>(_channel, logEntryReader))
            {
                reader.Next();
                TransactionRepresentation result = reader.Get().TransactionRepresentation;
                assertArrayEquals(additionalHeader, result.AdditionalHeader());
                assertEquals(masterId, result.MasterId);
                assertEquals(authorId, result.AuthorId);
                assertEquals(timeStarted, result.TimeStarted);
                assertEquals(timeCommitted, result.TimeCommitted);
                assertEquals(latestCommittedTxWhenStarted, result.LatestCommittedTxWhenStarted);
            }
        }
//JAVA TO C# CONVERTER TODO TASK: Most Java annotations will not have direct .NET equivalent attributes:
//ORIGINAL LINE: @Test public void shouldNotAppendCommittedTransactionsWhenTooFarAhead()
        public virtual void ShouldNotAppendCommittedTransactionsWhenTooFarAhead()
        {
            // GIVEN
            InMemoryClosableChannel channel = new InMemoryClosableChannel();

            when(_logFile.Writer).thenReturn(channel);
            TransactionAppender appender = Life.add(CreateTransactionAppender());

            // WHEN
//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;
            PhysicalTransactionRepresentation transactionRepresentation = new PhysicalTransactionRepresentation(SingleCreateNodeCommand(0));

            transactionRepresentation.SetHeader(additionalHeader, masterId, authorId, timeStarted, latestCommittedTxWhenStarted, timeCommitted, -1);

            when(_transactionIdStore.LastCommittedTransactionId).thenReturn(latestCommittedTxWhenStarted);

            LogEntryStart  start  = new LogEntryStart(0, 0, 0L, latestCommittedTxWhenStarted, null, LogPosition.UNSPECIFIED);
            LogEntryCommit commit = new LogEntryCommit(latestCommittedTxWhenStarted + 2, 0L);
            CommittedTransactionRepresentation transaction = new CommittedTransactionRepresentation(start, transactionRepresentation, commit);

            try
            {
                appender.Append(new TransactionToApply(transaction.TransactionRepresentation, transaction.CommitEntry.TxId), _logAppendEvent);
                fail("should have thrown");
            }
            catch (Exception e)
            {
                assertThat(e.Message, containsString("to be applied, but appending it ended up generating an"));
            }
        }
Beispiel #5
0
//JAVA TO C# CONVERTER WARNING: Method 'throws' clauses are not available in C#:
//ORIGINAL LINE: public void init() throws Throwable
        public override void Init()
        {
            RecoveryStartInformation recoveryStartInformation = _recoveryService.RecoveryStartInformation;

            if (!recoveryStartInformation.RecoveryRequired)
            {
                // If there is nothing to recovery, then the schema is initialised immediately.
                _schemaLife.init();
                return;
            }

            LogPosition recoveryPosition = recoveryStartInformation.RecoveryPosition;

            _monitor.recoveryRequired(recoveryPosition);
            _recoveryService.startRecovery();

            LogPosition recoveryToPosition = recoveryPosition;
            CommittedTransactionRepresentation lastTransaction         = null;
            CommittedTransactionRepresentation lastReversedTransaction = null;

            try
            {
                long lowestRecoveredTxId = Org.Neo4j.Kernel.impl.transaction.log.TransactionIdStore_Fields.BASE_TX_ID;
                using (TransactionCursor transactionsToRecover = _recoveryService.getTransactionsInReverseOrder(recoveryPosition), RecoveryApplier recoveryVisitor = _recoveryService.getRecoveryApplier(REVERSE_RECOVERY))
                {
                    while (transactionsToRecover.next())
                    {
                        CommittedTransactionRepresentation transaction = transactionsToRecover.get();
                        if (lastReversedTransaction == null)
                        {
                            lastReversedTransaction = transaction;
                            InitProgressReporter(recoveryStartInformation, lastReversedTransaction);
                        }
                        recoveryVisitor.visit(transaction);
                        lowestRecoveredTxId = transaction.CommitEntry.TxId;
                        ReportProgress();
                    }
                }

                _monitor.reverseStoreRecoveryCompleted(lowestRecoveredTxId);

                // We cannot initialise the schema (tokens, schema cache, indexing service, etc.) until we have returned the store to a consistent state.
                // We need to be able to read the store before we can even figure out what indexes, tokens, etc. we have. Hence we defer the initialisation
                // of the schema life until after we've done the reverse recovery.
                _schemaLife.init();

                using (TransactionCursor transactionsToRecover = _recoveryService.getTransactions(recoveryPosition), RecoveryApplier recoveryVisitor = _recoveryService.getRecoveryApplier(RECOVERY))
                {
                    while (transactionsToRecover.next())
                    {
                        lastTransaction = transactionsToRecover.get();
                        long txId = lastTransaction.CommitEntry.TxId;
                        recoveryVisitor.visit(lastTransaction);
                        _monitor.transactionRecovered(txId);
                        _numberOfRecoveredTransactions++;
                        recoveryToPosition = transactionsToRecover.Position();
                        ReportProgress();
                    }
                    recoveryToPosition = transactionsToRecover.Position();
                }
            }
            catch (Exception e) when(e is Exception || e is ClosedByInterruptException)
            {
                // We do not want to truncate logs based on these exceptions. Since users can influence them with config changes
                // the users are able to workaround this if truncations is really needed.
                throw e;
            }
            catch (Exception t)
            {
                if (_failOnCorruptedLogFiles)
                {
                    ThrowUnableToCleanRecover(t);
                }
                if (lastTransaction != null)
                {
                    LogEntryCommit commitEntry = lastTransaction.CommitEntry;
                    _monitor.failToRecoverTransactionsAfterCommit(t, commitEntry, recoveryToPosition);
                }
                else
                {
                    _monitor.failToRecoverTransactionsAfterPosition(t, recoveryPosition);
                    recoveryToPosition = recoveryPosition;
                }
            }
            _progressReporter.completed();
            _logsTruncator.truncate(recoveryToPosition);

            _recoveryService.transactionsRecovered(lastTransaction, recoveryToPosition);
            _monitor.recoveryCompleted(_numberOfRecoveredTransactions);
        }
Beispiel #6
0
 public override void FailToRecoverTransactionsAfterCommit(Exception t, LogEntryCommit commitEntry, LogPosition recoveryToPosition)
 {
     _log.warn(format("Fail to recover all transactions. Last recoverable transaction id:%d, committed " + "at:%d. Any later transaction after %s are unreadable and will be truncated.", commitEntry.TxId, commitEntry.TimeWritten, recoveryToPosition), t);
 }
Beispiel #7
0
 private static bool TransactionIdMakesSense(LogEntryCommit entry)
 {
     return(entry.TxId > Org.Neo4j.Kernel.impl.transaction.log.TransactionIdStore_Fields.BASE_TX_ID);
 }
Beispiel #8
0
 private static bool CommitEntryMakesSense(LogEntryCommit entry)
 {
     return(TimeMakesSense(entry.TimeWritten) && TransactionIdMakesSense(entry));
 }