Ejemplo n.º 1
0
        /// <summary>
        /// Rotates the current log file, continuing into next (version) log file.
        /// This method must be recovery safe, which means a crash at any point should be recoverable.
        /// Concurrent readers must also be able to parry for concurrent rotation.
        /// Concurrent writes will not be an issue since rotation and writing contends on the same monitor.
        ///
        /// Steps during rotation are:
        /// <ol>
        /// <li>1: Increment log version, <seealso cref="LogVersionRepository.incrementAndGetVersion()"/> (also flushes the store)</li>
        /// <li>2: Flush current log</li>
        /// <li>3: Create new log file</li>
        /// <li>4: Write header</li>
        /// </ol>
        ///
        /// Recovery: what happens if crash between:
        /// <ol>
        /// <li>1-2: New log version has been set, starting the writer will create the new log file idempotently.
        /// At this point there may have been half-written transactions in the previous log version,
        /// although they haven't been considered committed and so they will be truncated from log during recovery</li>
        /// <li>2-3: New log version has been set, starting the writer will create the new log file idempotently.
        /// At this point there may be complete transactions in the previous log version which may not have been
        /// acknowledged to be committed back to the user, but will be considered committed anyway.</li>
        /// <li>3-4: New log version has been set, starting the writer will see that the new file exists and
        /// will be forgiving when trying to read the header of it, so that if it isn't complete a fresh
        /// header will be set.</li>
        /// </ol>
        ///
        /// Reading: what happens when rotation is between:
        /// <ol>
        /// <li>1-2: Reader bridge will see that there's a new version (when asking <seealso cref="LogVersionRepository"/>
        /// and try to open it. The log file doesn't exist yet though. The bridge can parry for this by catching
        /// <seealso cref="FileNotFoundException"/> and tell the reader that the stream has ended</li>
        /// <li>2-3: Same as (1-2)</li>
        /// <li>3-4: Here the new log file exists, but the header may not be fully written yet.
        /// the reader will fail when trying to read the header since it's reading it strictly and bridge
        /// catches that exception, treating it the same as if the file didn't exist.</li>
        /// </ol>
        /// </summary>
        /// <param name="currentLog"> current <seealso cref="LogVersionedStoreChannel channel"/> to flush and close. </param>
        /// <returns> the channel of the newly opened/created log file. </returns>
        /// <exception cref="IOException"> if an error regarding closing or opening log files occur. </exception>
//JAVA TO C# CONVERTER WARNING: Method 'throws' clauses are not available in C#:
//ORIGINAL LINE: private org.neo4j.kernel.impl.transaction.log.PhysicalLogVersionedStoreChannel rotate(org.neo4j.kernel.impl.transaction.log.LogVersionedStoreChannel currentLog) throws java.io.IOException
        private PhysicalLogVersionedStoreChannel Rotate(LogVersionedStoreChannel currentLog)
        {
            /*
             * The store is now flushed. If we fail now the recovery code will open the
             * current log file and replay everything. That's unnecessary but totally ok.
             */
            long newLogVersion = _logVersionRepository.incrementAndGetVersion();

            /*
             * Rotation can happen at any point, although not concurrently with an append,
             * although an append may have (most likely actually) left at least some bytes left
             * in the buffer for future flushing. Flushing that buffer now makes the last appended
             * transaction complete in the log we're rotating away. Awesome.
             */
            _writer.prepareForFlush().flush();

            /*
             * The log version is now in the store, flushed and persistent. If we crash
             * now, on recovery we'll attempt to open the version we're about to create
             * (but haven't yet), discover it's not there. That will lead to creating
             * the file, setting the header and continuing.
             * We using committing transaction id as a source of last transaction id here since
             * we can have transactions that are not yet published as committed but were already stored
             * into transaction log that was just rotated.
             */
            PhysicalLogVersionedStoreChannel newLog = _logFiles.createLogChannelForVersion(newLogVersion, OpenMode.READ_WRITE, _context.committingTransactionId);

            currentLog.close();
            return(newLog);
        }
Ejemplo n.º 2
0
//JAVA TO C# CONVERTER TODO TASK: Most Java annotations will not have direct .NET equivalent attributes:
//ORIGINAL LINE: @Test public void skipLogFileWithoutHeader() throws java.io.IOException
//JAVA TO C# CONVERTER WARNING: Method 'throws' clauses are not available in C#:
        public virtual void SkipLogFileWithoutHeader()
        {
            FileSystemAbstraction fs = _fileSystemRule.get();
            LogFiles logFiles        = LogFilesBuilder.builder(_directory.databaseLayout(), fs).withTransactionIdStore(_transactionIdStore).withLogVersionRepository(_logVersionRepository).build();

            _life.add(logFiles);
            _life.start();

            // simulate new file without header presence
            _logVersionRepository.incrementAndGetVersion();
            fs.Create(logFiles.GetLogFileForVersion(_logVersionRepository.CurrentLogVersion)).close();
            _transactionIdStore.transactionCommitted(5L, 5L, 5L);

            PhysicalLogicalTransactionStore.LogVersionLocator versionLocator = new PhysicalLogicalTransactionStore.LogVersionLocator(4L);
            logFiles.Accept(versionLocator);

            LogPosition logPosition = versionLocator.LogPosition;

            assertEquals(1, logPosition.LogVersion);
        }