From 13fd1dc711d8d3db4cc8659e67cf69e399b62595 Mon Sep 17 00:00:00 2001 From: Anton Klaren Date: Mon, 21 Aug 2017 08:59:08 +0200 Subject: [PATCH] Removed legacy log files from 2.2 and backwards --- .../RecordStorageCommandReaderFactory.java | 14 +- .../legacylogs/LegacyLogEntryReader.java | 79 -- .../legacylogs/LegacyLogEntryWriter.java | 117 --- .../legacylogs/LegacyLogFilenames.java | 64 -- .../storemigration/legacylogs/LegacyLogs.java | 191 ----- .../legacylogs/LogEntrySortingCursor.java | 128 ---- .../participant/StoreMigrator.java | 24 +- .../command/PhysicalLogCommandReaderV2_0.java | 461 ------------ .../command/PhysicalLogCommandReaderV2_1.java | 485 ------------- .../command/PhysicalLogCommandReaderV2_2.java | 678 ------------------ .../log/entry/IdentifiableLogEntry.java | 87 --- .../log/entry/LogEntryByteCodes.java | 5 +- .../log/entry/LogEntryCommand.java | 1 + .../log/entry/LogEntryParsersV2_0.java | 231 ------ .../log/entry/LogEntryParsersV2_1.java | 224 ------ .../log/entry/LogEntryParsersV2_2.java | 133 ---- .../log/entry/LogEntryParsersV2_2_4.java | 133 ---- .../log/entry/LogEntryParsersV2_3.java | 2 +- .../transaction/log/entry/LogEntrySanity.java | 14 +- .../transaction/log/entry/LogEntryStart.java | 3 +- .../log/entry/LogEntryVersion.java | 30 +- .../log/entry/LogHeaderReader.java | 4 +- .../transaction/log/entry/OnePhaseCommit.java | 1 + .../log/entry/VersionAwareLogEntryReader.java | 25 +- .../legacylogs/LegacyLogEntryReaderTest.java | 138 ---- .../legacylogs/LegacyLogEntryWriterTest.java | 149 ---- .../legacylogs/LegacyLogsTest.java | 289 -------- .../legacylogs/LogEntrySortingCursorTest.java | 197 ----- .../participant/StoreMigratorTest.java | 40 -- .../PhysicalLogCommandReaderV2_1Test.java | 94 --- .../PhysicalLogCommandReadersTest.java | 18 - .../entry/LogEntryParserDispatcherV6Test.java | 24 +- .../log/entry/LogEntryParserV2_1Test.java | 212 ------ .../log/entry/LogEntryParserV2_2Test.java | 139 ---- .../entry/VersionAwareLogEntryReaderTest.java | 199 ----- .../RelationshipGroupCommandV2_2Test.java | 82 --- .../state/SchemaRuleCommandTest.java | 5 +- .../test/java/upgrade/StoreUpgraderTest.java | 57 -- 38 files changed, 35 insertions(+), 4742 deletions(-) delete mode 100644 community/kernel/src/main/java/org/neo4j/kernel/impl/storemigration/legacylogs/LegacyLogEntryReader.java delete mode 100644 community/kernel/src/main/java/org/neo4j/kernel/impl/storemigration/legacylogs/LegacyLogEntryWriter.java delete mode 100644 community/kernel/src/main/java/org/neo4j/kernel/impl/storemigration/legacylogs/LegacyLogFilenames.java delete mode 100644 community/kernel/src/main/java/org/neo4j/kernel/impl/storemigration/legacylogs/LegacyLogs.java delete mode 100644 community/kernel/src/main/java/org/neo4j/kernel/impl/storemigration/legacylogs/LogEntrySortingCursor.java delete mode 100644 community/kernel/src/main/java/org/neo4j/kernel/impl/transaction/command/PhysicalLogCommandReaderV2_0.java delete mode 100644 community/kernel/src/main/java/org/neo4j/kernel/impl/transaction/command/PhysicalLogCommandReaderV2_1.java delete mode 100644 community/kernel/src/main/java/org/neo4j/kernel/impl/transaction/command/PhysicalLogCommandReaderV2_2.java delete mode 100644 community/kernel/src/main/java/org/neo4j/kernel/impl/transaction/log/entry/IdentifiableLogEntry.java delete mode 100644 community/kernel/src/main/java/org/neo4j/kernel/impl/transaction/log/entry/LogEntryParsersV2_0.java delete mode 100644 community/kernel/src/main/java/org/neo4j/kernel/impl/transaction/log/entry/LogEntryParsersV2_1.java delete mode 100644 community/kernel/src/main/java/org/neo4j/kernel/impl/transaction/log/entry/LogEntryParsersV2_2.java delete mode 100644 community/kernel/src/main/java/org/neo4j/kernel/impl/transaction/log/entry/LogEntryParsersV2_2_4.java delete mode 100644 community/kernel/src/test/java/org/neo4j/kernel/impl/storemigration/legacylogs/LegacyLogEntryReaderTest.java delete mode 100644 community/kernel/src/test/java/org/neo4j/kernel/impl/storemigration/legacylogs/LegacyLogEntryWriterTest.java delete mode 100644 community/kernel/src/test/java/org/neo4j/kernel/impl/storemigration/legacylogs/LegacyLogsTest.java delete mode 100644 community/kernel/src/test/java/org/neo4j/kernel/impl/storemigration/legacylogs/LogEntrySortingCursorTest.java delete mode 100644 community/kernel/src/test/java/org/neo4j/kernel/impl/transaction/command/PhysicalLogCommandReaderV2_1Test.java delete mode 100644 community/kernel/src/test/java/org/neo4j/kernel/impl/transaction/log/entry/LogEntryParserV2_1Test.java delete mode 100644 community/kernel/src/test/java/org/neo4j/kernel/impl/transaction/log/entry/LogEntryParserV2_2Test.java delete mode 100644 community/kernel/src/test/java/org/neo4j/kernel/impl/transaction/state/RelationshipGroupCommandV2_2Test.java diff --git a/community/kernel/src/main/java/org/neo4j/kernel/impl/storageengine/impl/recordstorage/RecordStorageCommandReaderFactory.java b/community/kernel/src/main/java/org/neo4j/kernel/impl/storageengine/impl/recordstorage/RecordStorageCommandReaderFactory.java index 44aa30ba9815f..a05c8dd461d68 100644 --- a/community/kernel/src/main/java/org/neo4j/kernel/impl/storageengine/impl/recordstorage/RecordStorageCommandReaderFactory.java +++ b/community/kernel/src/main/java/org/neo4j/kernel/impl/storageengine/impl/recordstorage/RecordStorageCommandReaderFactory.java @@ -19,9 +19,6 @@ */ package org.neo4j.kernel.impl.storageengine.impl.recordstorage; -import org.neo4j.kernel.impl.transaction.command.PhysicalLogCommandReaderV2_0; -import org.neo4j.kernel.impl.transaction.command.PhysicalLogCommandReaderV2_1; -import org.neo4j.kernel.impl.transaction.command.PhysicalLogCommandReaderV2_2; import org.neo4j.kernel.impl.transaction.command.PhysicalLogCommandReaderV2_2_10; import org.neo4j.kernel.impl.transaction.command.PhysicalLogCommandReaderV2_2_4; import org.neo4j.kernel.impl.transaction.command.PhysicalLogCommandReaderV3_0; @@ -40,13 +37,8 @@ public class RecordStorageCommandReaderFactory implements CommandReaderFactory public RecordStorageCommandReaderFactory() { readers = new CommandReader[11]; // pessimistic size - readers[-LogEntryVersion.V2_0.byteCode()] = new PhysicalLogCommandReaderV2_0(); - readers[-LogEntryVersion.V2_1.byteCode()] = new PhysicalLogCommandReaderV2_1(); - readers[-LogEntryVersion.V2_2.byteCode()] = new PhysicalLogCommandReaderV2_2(); - readers[-LogEntryVersion.V2_2_4.byteCode()] = new PhysicalLogCommandReaderV2_2_4(); readers[-LogEntryVersion.V2_3.byteCode()] = new PhysicalLogCommandReaderV2_2_4(); readers[-LogEntryVersion.V3_0.byteCode()] = new PhysicalLogCommandReaderV3_0(); - readers[-LogEntryVersion.V2_2_10.byteCode()] = new PhysicalLogCommandReaderV2_2_10(); readers[-LogEntryVersion.V2_3_5.byteCode()] = new PhysicalLogCommandReaderV2_2_10(); readers[-LogEntryVersion.V3_0_2.byteCode()] = new PhysicalLogCommandReaderV3_0_2(); // The 3_0_10 version bump is only to prevent mixed-version clusters; format is otherwise backwards compatible. @@ -54,11 +46,11 @@ public RecordStorageCommandReaderFactory() // A little extra safety check so that we got 'em all LogEntryVersion[] versions = LogEntryVersion.values(); - for ( int i = 0; i < versions.length; i++ ) + for ( LogEntryVersion version : versions ) { - if ( versions[i] == null ) + if ( version == null ) { - throw new IllegalStateException( "Version " + versions[i] + " not handled" ); + throw new IllegalStateException( "Version " + version + " not handled" ); } } } diff --git a/community/kernel/src/main/java/org/neo4j/kernel/impl/storemigration/legacylogs/LegacyLogEntryReader.java b/community/kernel/src/main/java/org/neo4j/kernel/impl/storemigration/legacylogs/LegacyLogEntryReader.java deleted file mode 100644 index 548dd6b01e056..0000000000000 --- a/community/kernel/src/main/java/org/neo4j/kernel/impl/storemigration/legacylogs/LegacyLogEntryReader.java +++ /dev/null @@ -1,79 +0,0 @@ -/* - * Copyright (c) 2002-2017 "Neo Technology," - * Network Engine for Objects in Lund AB [http://neotechnology.com] - * - * This file is part of Neo4j. - * - * Neo4j is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ -package org.neo4j.kernel.impl.storemigration.legacylogs; - -import java.io.File; -import java.io.IOException; -import java.nio.ByteBuffer; -import java.util.function.Function; - -import org.neo4j.cursor.IOCursor; -import org.neo4j.helpers.collection.Pair; -import org.neo4j.io.fs.FileSystemAbstraction; -import org.neo4j.io.fs.StoreChannel; -import org.neo4j.kernel.impl.transaction.log.PhysicalLogVersionedStoreChannel; -import org.neo4j.kernel.impl.transaction.log.ReadAheadLogChannel; -import org.neo4j.kernel.impl.transaction.log.ReadableLogChannel; -import org.neo4j.kernel.impl.transaction.log.entry.LogEntry; -import org.neo4j.kernel.impl.transaction.log.entry.LogEntryReader; -import org.neo4j.kernel.impl.transaction.log.entry.LogHeader; -import org.neo4j.kernel.impl.transaction.log.entry.VersionAwareLogEntryReader; - -import static org.neo4j.kernel.impl.transaction.log.LogVersionBridge.NO_MORE_CHANNELS; -import static org.neo4j.kernel.impl.transaction.log.TransactionIdStore.BASE_TX_ID; -import static org.neo4j.kernel.impl.transaction.log.entry.LogHeader.LOG_HEADER_SIZE; -import static org.neo4j.kernel.impl.transaction.log.entry.LogHeaderReader.readLogHeader; -import static org.neo4j.kernel.impl.transaction.log.entry.LogVersions.CURRENT_LOG_VERSION; - -class LegacyLogEntryReader -{ - private final FileSystemAbstraction fs; - private final Function> readerFactory; - - LegacyLogEntryReader( FileSystemAbstraction fs, - Function> readerFactory ) - { - this.fs = fs; - this.readerFactory = readerFactory; - } - - LegacyLogEntryReader( FileSystemAbstraction fs ) - { - this( fs, from -> new VersionAwareLogEntryReader<>() ); - } - - public Pair> openReadableChannel( File logFile ) throws IOException - { - final StoreChannel rawChannel = fs.open( logFile, "r" ); - - final LogHeader header = readLogHeader( ByteBuffer.allocate( LOG_HEADER_SIZE ), rawChannel, false, logFile ); - LogEntryReader reader = readerFactory.apply( header ); - - // this ensures that the last committed txId field in the header is initialized properly - long lastCommittedTxId = Math.max( BASE_TX_ID, header.lastCommittedTxId ); - - final PhysicalLogVersionedStoreChannel channel = - new PhysicalLogVersionedStoreChannel( rawChannel, header.logVersion, header.logFormatVersion ); - final ReadableLogChannel readableChannel = new ReadAheadLogChannel( channel, NO_MORE_CHANNELS ); - final IOCursor cursor = new LogEntrySortingCursor( reader, readableChannel ); - - return Pair.of( new LogHeader( CURRENT_LOG_VERSION, header.logVersion, lastCommittedTxId ), cursor ); - } -} diff --git a/community/kernel/src/main/java/org/neo4j/kernel/impl/storemigration/legacylogs/LegacyLogEntryWriter.java b/community/kernel/src/main/java/org/neo4j/kernel/impl/storemigration/legacylogs/LegacyLogEntryWriter.java deleted file mode 100644 index 22575f011c52c..0000000000000 --- a/community/kernel/src/main/java/org/neo4j/kernel/impl/storemigration/legacylogs/LegacyLogEntryWriter.java +++ /dev/null @@ -1,117 +0,0 @@ -/* - * Copyright (c) 2002-2017 "Neo Technology," - * Network Engine for Objects in Lund AB [http://neotechnology.com] - * - * This file is part of Neo4j. - * - * Neo4j is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ -package org.neo4j.kernel.impl.storemigration.legacylogs; - -import java.io.File; -import java.io.IOException; -import java.util.ArrayList; -import java.util.List; -import java.util.function.Function; - -import org.neo4j.cursor.IOCursor; -import org.neo4j.io.fs.FileSystemAbstraction; -import org.neo4j.io.fs.StoreChannel; -import org.neo4j.kernel.impl.transaction.log.FlushableChannel; -import org.neo4j.kernel.impl.transaction.log.LogVersionedStoreChannel; -import org.neo4j.kernel.impl.transaction.log.PhysicalLogVersionedStoreChannel; -import org.neo4j.kernel.impl.transaction.log.PhysicalTransactionRepresentation; -import org.neo4j.kernel.impl.transaction.log.PositionAwarePhysicalFlushableChannel; -import org.neo4j.kernel.impl.transaction.log.entry.LogEntry; -import org.neo4j.kernel.impl.transaction.log.entry.LogEntryCommand; -import org.neo4j.kernel.impl.transaction.log.entry.LogEntryCommit; -import org.neo4j.kernel.impl.transaction.log.entry.LogEntryStart; -import org.neo4j.kernel.impl.transaction.log.entry.LogEntryWriter; -import org.neo4j.kernel.impl.transaction.log.entry.LogHeader; -import org.neo4j.kernel.impl.transaction.log.entry.LogHeaderWriter; -import org.neo4j.storageengine.api.StorageCommand; - -import static org.neo4j.kernel.impl.storemigration.legacylogs.LegacyLogFilenames.getLegacyLogVersion; -import static org.neo4j.kernel.impl.transaction.log.entry.LogVersions.CURRENT_LOG_VERSION; - -class LegacyLogEntryWriter -{ - private static final Function defaultLogEntryWriterFactory = - LogEntryWriter::new; - - private final FileSystemAbstraction fs; - private final Function factory; - - LegacyLogEntryWriter( FileSystemAbstraction fs ) - { - this( fs, defaultLogEntryWriterFactory ); - } - - LegacyLogEntryWriter( FileSystemAbstraction fs, Function factory ) - { - this.fs = fs; - this.factory = factory; - } - - public LogVersionedStoreChannel openWritableChannel( File file ) throws IOException - { - final StoreChannel storeChannel = fs.open( file, "rw" ); - final long version = getLegacyLogVersion( file.getName() ); - return new PhysicalLogVersionedStoreChannel( storeChannel, version, CURRENT_LOG_VERSION ); - } - - public void writeLogHeader( LogVersionedStoreChannel channel, LogHeader header ) throws IOException - { - LogHeaderWriter.writeLogHeader( channel, header.logVersion, header.lastCommittedTxId ); - } - - public void writeAllLogEntries( LogVersionedStoreChannel channel, IOCursor cursor ) throws IOException - { - try ( PositionAwarePhysicalFlushableChannel writable = new PositionAwarePhysicalFlushableChannel( channel ) ) - { - final LogEntryWriter writer = factory.apply( writable ); - List commands = new ArrayList<>(); - while ( cursor.next() ) - { - LogEntry entry = cursor.get(); - if ( entry instanceof LogEntryStart ) - { - final LogEntryStart startEntry = entry.as(); - writer.writeStartEntry( startEntry.getMasterId(), startEntry.getLocalId(), - startEntry.getTimeWritten(), startEntry.getLastCommittedTxWhenTransactionStarted(), - startEntry.getAdditionalHeader() ); - } - else if ( entry instanceof LogEntryCommit ) - { - if ( !commands.isEmpty() ) - { - writer.serialize( new PhysicalTransactionRepresentation( commands ) ); - commands = new ArrayList<>(); - } - - final LogEntryCommit commitEntry = (LogEntryCommit) entry; - writer.writeCommitEntry( commitEntry.getTxId(), commitEntry.getTimeWritten() ); - } - else if ( entry instanceof LogEntryCommand ) - { - commands.add( ((LogEntryCommand) entry).getXaCommand() ); - } - else - { - throw new IllegalStateException( "Unknown entry: " + entry ); - } - } - } - } -} diff --git a/community/kernel/src/main/java/org/neo4j/kernel/impl/storemigration/legacylogs/LegacyLogFilenames.java b/community/kernel/src/main/java/org/neo4j/kernel/impl/storemigration/legacylogs/LegacyLogFilenames.java deleted file mode 100644 index 694d2ea481640..0000000000000 --- a/community/kernel/src/main/java/org/neo4j/kernel/impl/storemigration/legacylogs/LegacyLogFilenames.java +++ /dev/null @@ -1,64 +0,0 @@ -/* - * Copyright (c) 2002-2017 "Neo Technology," - * Network Engine for Objects in Lund AB [http://neotechnology.com] - * - * This file is part of Neo4j. - * - * Neo4j is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ -package org.neo4j.kernel.impl.storemigration.legacylogs; - -import java.io.FilenameFilter; - -public class LegacyLogFilenames -{ - private static final String legacyLogFilesPrefix = "nioneo_logical.log.v"; - private static final String versionedLegacyLogFilesPattern = "nioneo_logical\\.log\\.v\\d+"; - private static final String[] allLegacyLogFilesPatterns = - {"active_tx_log", "tm_tx_log\\..*", "nioneo_logical\\.log\\..*"}; - - public static final FilenameFilter versionedLegacyLogFilesFilter = - ( dir, name ) -> name.matches( versionedLegacyLogFilesPattern ); - - static final FilenameFilter allLegacyLogFilesFilter = ( dir, name ) -> - { - for ( String pattern : allLegacyLogFilesPatterns ) - { - if ( name.matches( pattern ) ) - { - return true; - } - } - return false; - }; - - private LegacyLogFilenames() - { - } - - static long getLegacyLogVersion( String filename ) - { - int index = filename.lastIndexOf( ".v" ); - if ( index == -1 ) - { - throw new RuntimeException( "Invalid log file '" + filename + "'" ); - } - return Long.parseLong( filename.substring( index + ".v".length() ) ); - } - - static String getLegacyLogFilename( int version ) - { - return legacyLogFilesPrefix + version; - } -} diff --git a/community/kernel/src/main/java/org/neo4j/kernel/impl/storemigration/legacylogs/LegacyLogs.java b/community/kernel/src/main/java/org/neo4j/kernel/impl/storemigration/legacylogs/LegacyLogs.java deleted file mode 100644 index 1ff3f74fe967c..0000000000000 --- a/community/kernel/src/main/java/org/neo4j/kernel/impl/storemigration/legacylogs/LegacyLogs.java +++ /dev/null @@ -1,191 +0,0 @@ -/* - * Copyright (c) 2002-2017 "Neo Technology," - * Network Engine for Objects in Lund AB [http://neotechnology.com] - * - * This file is part of Neo4j. - * - * Neo4j is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ -package org.neo4j.kernel.impl.storemigration.legacylogs; - -import java.io.File; -import java.io.IOException; -import java.util.Arrays; -import java.util.Comparator; -import java.util.List; -import java.util.Optional; - -import org.neo4j.cursor.IOCursor; -import org.neo4j.helpers.collection.Pair; -import org.neo4j.io.fs.FileSystemAbstraction; -import org.neo4j.kernel.impl.store.TransactionId; -import org.neo4j.kernel.impl.storemigration.ExistingTargetStrategy; -import org.neo4j.kernel.impl.storemigration.FileOperation; -import org.neo4j.kernel.impl.transaction.log.LogVersionedStoreChannel; -import org.neo4j.kernel.impl.transaction.log.entry.LogEntry; -import org.neo4j.kernel.impl.transaction.log.entry.LogEntryCommit; -import org.neo4j.kernel.impl.transaction.log.entry.LogEntryStart; -import org.neo4j.kernel.impl.transaction.log.entry.LogHeader; - -import static org.neo4j.kernel.impl.storemigration.legacylogs.LegacyLogFilenames.allLegacyLogFilesFilter; -import static org.neo4j.kernel.impl.storemigration.legacylogs.LegacyLogFilenames.getLegacyLogVersion; -import static org.neo4j.kernel.impl.storemigration.legacylogs.LegacyLogFilenames.versionedLegacyLogFilesFilter; -import static org.neo4j.kernel.impl.transaction.log.PhysicalLogFile.DEFAULT_NAME; -import static org.neo4j.kernel.impl.transaction.log.PhysicalLogFile.DEFAULT_VERSION_SUFFIX; - -public class LegacyLogs -{ - private final FileSystemAbstraction fs; - private final LegacyLogEntryReader reader; - private final LegacyLogEntryWriter writer; - private final Comparator NEWEST_FIRST = new Comparator() - { - @Override - public int compare( File o1, File o2 ) - { - return versionOf( o1 ).compareTo( versionOf( o2 ) ); - } - - private Long versionOf( File file ) - { - Pair> pair = null; - try - { - pair = reader.openReadableChannel( file ); - LogHeader header = pair.first(); - return Long.valueOf( header.logVersion ); - } - catch ( IOException e ) - { // Shouldn't happen - throw new RuntimeException( e ); - } - finally - { - if ( pair != null ) - { - try - { - pair.other().close(); - } - catch ( IOException e ) - { - throw new RuntimeException( e ); - } - } - } - } - }; - - public LegacyLogs( FileSystemAbstraction fs ) - { - this( fs, new LegacyLogEntryReader( fs ), new LegacyLogEntryWriter( fs ) ); - } - - LegacyLogs( FileSystemAbstraction fs, LegacyLogEntryReader reader, LegacyLogEntryWriter writer ) - { - this.fs = fs; - this.reader = reader; - this.writer = writer; - } - - public void migrateLogs( File storeDir, File migrationDir ) throws IOException - { - File[] logFiles = fs.listFiles( storeDir, versionedLegacyLogFilesFilter ); - for ( File file : logFiles ) - { - final Pair> pair = reader.openReadableChannel( file ); - final LogHeader header = pair.first(); - - try ( IOCursor cursor = pair.other(); - LogVersionedStoreChannel channel = - writer.openWritableChannel( new File( migrationDir, file.getName() ) ) ) - { - writer.writeLogHeader( channel, header ); - writer.writeAllLogEntries( channel, cursor ); - } - } - } - - public Optional getTransactionInformation( File storeDir, long transactionId ) throws IOException - { - List logFiles = Arrays.asList( fs.listFiles( storeDir, versionedLegacyLogFilesFilter ) ); - logFiles.sort( NEWEST_FIRST ); - for ( File file : logFiles ) - { - Pair> pair = reader.openReadableChannel( file ); - boolean hadAnyTransactions = false; - try ( IOCursor cursor = pair.other() ) - { - // The log entries will come sorted from this cursor, so no need to keep track of identifiers and such. - LogEntryStart startEntry = null; - while ( cursor.next() ) - { - LogEntry logEntry = cursor.get(); - if ( logEntry instanceof LogEntryStart ) - { - startEntry = (LogEntryStart) logEntry; - } - else if ( logEntry instanceof LogEntryCommit ) - { - hadAnyTransactions = true; - LogEntryCommit commitEntry = logEntry.as(); - if ( commitEntry.getTxId() == transactionId ) - { - return Optional.of( new TransactionId( transactionId, startEntry.checksum(), - commitEntry.getTimeWritten() ) ); - } - } - } - } - if ( hadAnyTransactions ) - { - // No need to go further back than this. We're looking for the last transaction - break; - } - } - return Optional.empty(); - } - - public void operate( FileOperation op, File from, File to ) throws IOException - { - File[] logFiles = fs.listFiles( from, versionedLegacyLogFilesFilter ); - for ( File file : logFiles ) - { - op.perform( fs, file.getName(), from, false, to, ExistingTargetStrategy.OVERWRITE ); - } - } - - public void renameLogFiles( File storeDir ) throws IOException - { - // rename files - for ( File file : fs.listFiles( storeDir, versionedLegacyLogFilesFilter ) ) - { - final String oldName = file.getName(); - final long version = getLegacyLogVersion( oldName ); - final String newName = DEFAULT_NAME + DEFAULT_VERSION_SUFFIX + version; - fs.renameFile( file, new File( file.getParent(), newName ) ); - } - - deleteUnusedLogFiles( storeDir ); - } - - public void deleteUnusedLogFiles( File storeDir ) - { - // delete old an unused log files - for ( File file : fs.listFiles( storeDir, allLegacyLogFilesFilter ) ) - { - fs.deleteFile( file ); - } - } -} diff --git a/community/kernel/src/main/java/org/neo4j/kernel/impl/storemigration/legacylogs/LogEntrySortingCursor.java b/community/kernel/src/main/java/org/neo4j/kernel/impl/storemigration/legacylogs/LogEntrySortingCursor.java deleted file mode 100644 index 408f0ce20fb65..0000000000000 --- a/community/kernel/src/main/java/org/neo4j/kernel/impl/storemigration/legacylogs/LogEntrySortingCursor.java +++ /dev/null @@ -1,128 +0,0 @@ -/* - * Copyright (c) 2002-2017 "Neo Technology," - * Network Engine for Objects in Lund AB [http://neotechnology.com] - * - * This file is part of Neo4j. - * - * Neo4j is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ -package org.neo4j.kernel.impl.storemigration.legacylogs; - -import java.io.IOException; -import java.util.ArrayList; -import java.util.HashMap; -import java.util.List; -import java.util.Map; - -import org.neo4j.cursor.IOCursor; -import org.neo4j.kernel.impl.transaction.log.ReadableLogChannel; -import org.neo4j.kernel.impl.transaction.log.entry.IdentifiableLogEntry; -import org.neo4j.kernel.impl.transaction.log.entry.LogEntry; -import org.neo4j.kernel.impl.transaction.log.entry.LogEntryCommit; -import org.neo4j.kernel.impl.transaction.log.entry.LogEntryReader; - -class LogEntrySortingCursor implements IOCursor -{ - private final ReadableLogChannel channel; - private final LogEntryReader reader; - // identifier -> log entry - private final Map> idToEntries = new HashMap<>(); - - private LogEntry toReturn; - private int idToFetchFrom = -1; - - LogEntrySortingCursor( LogEntryReader reader, - ReadableLogChannel channel ) - { - this.reader = reader; - this.channel = channel; - } - - @Override - public LogEntry get() - { - return toReturn; - } - - @Override - public boolean next() throws IOException - { - perhapsFetchEntriesFromChannel(); - - if ( idToFetchFrom < 0 ) - { - // nothing to available either from channel or from map... - toReturn = null; - return false; - } - - final List entries = idToEntries.get( idToFetchFrom ); - toReturn = entries.remove( 0 ); - if ( entries.isEmpty() ) - { - idToEntries.remove( idToFetchFrom ); - idToFetchFrom = -1; - } - - return true; - } - - private void perhapsFetchEntriesFromChannel() throws IOException - { - if ( idToFetchFrom > 0 ) - { - // we still have entry to return from the map... - return; - } - - LogEntry entry; - while ( (entry = reader.readLogEntry( channel )) != null ) - { - if ( !(entry instanceof IdentifiableLogEntry) ) - { - throw new IllegalStateException( "reading from a log which is not a legacy one???" ); - } - - final IdentifiableLogEntry identifiableLogEntry = (IdentifiableLogEntry) entry; - final int identifier = identifiableLogEntry.getIdentifier(); - final LogEntry inner = identifiableLogEntry.getEntry(); - - List list = provideList( idToEntries, identifier ); - list.add( inner ); - - if ( inner instanceof LogEntryCommit ) - { - idToFetchFrom = identifier; - break; - } - } - } - - private List provideList( Map> idToEntries, int identifier ) - { - List list = idToEntries.get( identifier ); - if ( list == null ) - { - list = new ArrayList<>(); - idToEntries.put( identifier, list ); - } - return list; - } - - @Override - public void close() throws IOException - { - channel.close(); - } -} diff --git a/community/kernel/src/main/java/org/neo4j/kernel/impl/storemigration/participant/StoreMigrator.java b/community/kernel/src/main/java/org/neo4j/kernel/impl/storemigration/participant/StoreMigrator.java index 435264b433fe5..17a4b68ddcc7a 100644 --- a/community/kernel/src/main/java/org/neo4j/kernel/impl/storemigration/participant/StoreMigrator.java +++ b/community/kernel/src/main/java/org/neo4j/kernel/impl/storemigration/participant/StoreMigrator.java @@ -39,7 +39,6 @@ import java.util.Optional; import java.util.function.BiConsumer; import java.util.function.Predicate; -import java.util.function.Supplier; import java.util.stream.StreamSupport; import org.neo4j.io.fs.FileHandle; @@ -78,7 +77,6 @@ import org.neo4j.kernel.impl.storemigration.ExistingTargetStrategy; import org.neo4j.kernel.impl.storemigration.StoreFileType; import org.neo4j.kernel.impl.storemigration.StoreUpgrader; -import org.neo4j.kernel.impl.storemigration.legacylogs.LegacyLogs; import org.neo4j.kernel.impl.storemigration.monitoring.MigrationProgressMonitor; import org.neo4j.kernel.impl.storemigration.monitoring.SilentMigrationProgressMonitor; import org.neo4j.kernel.impl.transaction.log.LogPosition; @@ -134,25 +132,17 @@ public class StoreMigrator extends AbstractStoreMigrationParticipant private final Config config; private final LogService logService; - private final LegacyLogs legacyLogs; private final FileSystemAbstraction fileSystem; private final PageCache pageCache; public StoreMigrator( FileSystemAbstraction fileSystem, PageCache pageCache, Config config, LogService logService ) - { - this( fileSystem, pageCache, config, logService, new LegacyLogs( fileSystem ) ); - } - - public StoreMigrator( FileSystemAbstraction fileSystem, PageCache pageCache, Config config, - LogService logService, LegacyLogs legacyLogs ) { super( "Store files" ); this.fileSystem = fileSystem; this.pageCache = pageCache; this.config = config; this.logService = logService; - this.legacyLogs = legacyLogs; } @Override @@ -290,15 +280,12 @@ TransactionId extractTransactionIdInformation( File neoStore, File storeDir, lon { return new TransactionId( lastTransactionId, checksum, commitTimestamp ); } - // The legacy store we're migrating doesn't have this record in neostore so try to extract it from tx log - Optional transactionInformation = legacyLogs - .getTransactionInformation( storeDir, lastTransactionId ); - return transactionInformation.orElseGet( specificTransactionInformationSupplier( lastTransactionId ) ); + return specificTransactionInformationSupplier( lastTransactionId ); } /** - * In case if we can't find information about transaction in legacy logs we will create new transaction + * In case if we can't find information about transaction in logs we will create new transaction * information record. * Those should be used only in case if we do not have any transaction logs available during * migration. @@ -313,9 +300,9 @@ TransactionId extractTransactionIdInformation( File neoStore, File storeDir, lon * @param lastTransactionId last committed transaction id * @return supplier of custom id records. */ - private Supplier specificTransactionInformationSupplier( long lastTransactionId ) + private TransactionId specificTransactionInformationSupplier( long lastTransactionId ) { - return () -> lastTransactionId == TransactionIdStore.BASE_TX_ID + return lastTransactionId == TransactionIdStore.BASE_TX_ID ? new TransactionId( lastTransactionId, BASE_TX_CHECKSUM, BASE_TX_COMMIT_TIMESTAMP ) : new TransactionId( lastTransactionId, UNKNOWN_TX_CHECKSUM, UNKNOWN_TX_COMMIT_TIMESTAMP ); } @@ -660,9 +647,6 @@ public void moveMigratedFiles( File migrationDir, File storeDir, String versionT { //This means that we had no files only present in the page cache, this is fine. } - - // delete old logs - legacyLogs.deleteUnusedLogFiles( storeDir ); } private void updateOrAddNeoStoreFieldsAsPartOfMigration( File migrationDir, File storeDir, diff --git a/community/kernel/src/main/java/org/neo4j/kernel/impl/transaction/command/PhysicalLogCommandReaderV2_0.java b/community/kernel/src/main/java/org/neo4j/kernel/impl/transaction/command/PhysicalLogCommandReaderV2_0.java deleted file mode 100644 index b1ce2b2f763d0..0000000000000 --- a/community/kernel/src/main/java/org/neo4j/kernel/impl/transaction/command/PhysicalLogCommandReaderV2_0.java +++ /dev/null @@ -1,461 +0,0 @@ -/* - * Copyright (c) 2002-2017 "Neo Technology," - * Network Engine for Objects in Lund AB [http://neotechnology.com] - * - * This file is part of Neo4j. - * - * Neo4j is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ -package org.neo4j.kernel.impl.transaction.command; - -import java.io.IOException; -import java.nio.ByteBuffer; -import java.util.ArrayList; -import java.util.Collection; - -import org.neo4j.helpers.collection.Iterables; -import org.neo4j.kernel.api.exceptions.schema.MalformedSchemaRuleException; -import org.neo4j.kernel.impl.store.AbstractDynamicStore; -import org.neo4j.kernel.impl.store.PropertyType; -import org.neo4j.kernel.impl.store.record.DynamicRecord; -import org.neo4j.kernel.impl.store.record.LabelTokenRecord; -import org.neo4j.kernel.impl.store.record.NeoStoreRecord; -import org.neo4j.kernel.impl.store.record.NodeRecord; -import org.neo4j.kernel.impl.store.record.PropertyBlock; -import org.neo4j.kernel.impl.store.record.PropertyKeyTokenRecord; -import org.neo4j.kernel.impl.store.record.PropertyRecord; -import org.neo4j.kernel.impl.store.record.Record; -import org.neo4j.kernel.impl.store.record.RelationshipRecord; -import org.neo4j.kernel.impl.store.record.RelationshipTypeTokenRecord; -import org.neo4j.kernel.impl.store.record.SchemaRuleSerialization; -import org.neo4j.kernel.impl.transaction.command.CommandReading.DynamicRecordAdder; -import org.neo4j.storageengine.api.ReadableChannel; -import org.neo4j.storageengine.api.schema.SchemaRule; - -import static org.neo4j.helpers.Exceptions.launderedException; -import static org.neo4j.kernel.impl.transaction.command.CommandReading.COLLECTION_DYNAMIC_RECORD_ADDER; -import static org.neo4j.kernel.impl.transaction.command.CommandReading.PROPERTY_BLOCK_DYNAMIC_RECORD_ADDER; -import static org.neo4j.kernel.impl.transaction.command.CommandReading.PROPERTY_DELETED_DYNAMIC_RECORD_ADDER; -import static org.neo4j.kernel.impl.transaction.command.CommandReading.PROPERTY_INDEX_DYNAMIC_RECORD_ADDER; - -public class PhysicalLogCommandReaderV2_0 extends BaseCommandReader -{ - @Override - protected Command read( byte commandType, ReadableChannel channel ) throws IOException - { - switch ( commandType ) - { - case NeoCommandType.NODE_COMMAND: - return visitNodeCommand( channel ); - case NeoCommandType.PROP_COMMAND: - return visitPropertyCommand( channel ); - case NeoCommandType.PROP_INDEX_COMMAND: - return visitPropertyKeyTokenCommand( channel ); - case NeoCommandType.REL_COMMAND: - return visitRelationshipCommand( channel ); - case NeoCommandType.REL_TYPE_COMMAND: - return visitRelationshipTypeTokenCommand( channel ); - case NeoCommandType.LABEL_KEY_COMMAND: - return visitLabelTokenCommand( channel ); - case NeoCommandType.NEOSTORE_COMMAND: - return visitNeoStoreCommand( channel ); - case NeoCommandType.SCHEMA_RULE_COMMAND: - return visitSchemaRuleCommand( channel ); - default: - throw unknownCommandType( commandType, channel ); - } - } - - private Command visitNodeCommand( ReadableChannel channel ) throws IOException - { - long id = channel.getLong(); - NodeRecord before = readNodeRecord( id, channel ); - if ( before == null ) - { - return null; - } - NodeRecord after = readNodeRecord( id, channel ); - if ( after == null ) - { - return null; - } - if ( !before.inUse() && after.inUse() ) - { - after.setCreated(); - } - return new Command.NodeCommand( before, after ); - } - - private Command visitRelationshipCommand( ReadableChannel channel ) throws IOException - { - long id = channel.getLong(); - byte inUseFlag = channel.get(); - boolean inUse = false; - if ( (inUseFlag & Record.IN_USE.byteValue()) == Record.IN_USE.byteValue() ) - { - inUse = true; - } - else if ( (inUseFlag & Record.IN_USE.byteValue()) != Record.NOT_IN_USE.byteValue() ) - { - throw new IOException( "Illegal in use flag: " + inUseFlag ); - } - RelationshipRecord record; - if ( inUse ) - { - record = new RelationshipRecord( id, channel.getLong(), channel.getLong(), channel.getInt() ); - record.setInUse( inUse ); - record.setFirstPrevRel( channel.getLong() ); - record.setFirstNextRel( channel.getLong() ); - record.setSecondPrevRel( channel.getLong() ); - record.setSecondNextRel( channel.getLong() ); - record.setNextProp( channel.getLong() ); - /* - * Logs for version 2.0 do not contain the proper values for the following two flags. Also, - * the defaults won't do, because the pointers for prev in the fist record will not be interpreted - * properly. So we need to set the flags explicitly here. - * - * Note that this leaves the prev field for the first record in the chain having a value of -1, - * which is not correct, as it should contain the relationship count instead. However, we cannot - * determine this value from the contents of the log alone. - */ - record.setFirstInFirstChain( record.getFirstPrevRel() == Record.NO_PREV_RELATIONSHIP.intValue() ); - record.setFirstInSecondChain( record.getSecondPrevRel() == Record.NO_PREV_RELATIONSHIP.intValue() ); - } - else - { - record = new RelationshipRecord( id ); - } - return new Command.RelationshipCommand( null, record ); - } - - protected Command visitPropertyCommand( ReadableChannel channel ) throws IOException - { - // ID - long id = channel.getLong(); // 8 - // BEFORE - PropertyRecord before = readPropertyRecord( id, channel ); - if ( before == null ) - { - return null; - } - // AFTER - PropertyRecord after = readPropertyRecord( id, channel ); - if ( after == null ) - { - return null; - } - return new Command.PropertyCommand( before, after ); - } - - private Command visitRelationshipTypeTokenCommand( ReadableChannel channel ) throws IOException - { - // id+in_use(byte)+type_blockId(int)+nr_type_records(int) - int id = channel.getInt(); - byte inUseFlag = channel.get(); - boolean inUse = false; - if ( (inUseFlag & Record.IN_USE.byteValue()) == Record.IN_USE.byteValue() ) - { - inUse = true; - } - else if ( inUseFlag != Record.NOT_IN_USE.byteValue() ) - { - throw new IOException( "Illegal in use flag: " + inUseFlag ); - } - RelationshipTypeTokenRecord record = new RelationshipTypeTokenRecord( id ); - record.setInUse( inUse ); - record.setNameId( channel.getInt() ); - int nrTypeRecords = channel.getInt(); - for ( int i = 0; i < nrTypeRecords; i++ ) - { - DynamicRecord dr = readDynamicRecord( channel ); - if ( dr == null ) - { - return null; - } - record.addNameRecord( dr ); - } - return new Command.RelationshipTypeTokenCommand( null, record ); - } - - private Command visitLabelTokenCommand( ReadableChannel channel ) throws IOException - { - // id+in_use(byte)+type_blockId(int)+nr_type_records(int) - int id = channel.getInt(); - byte inUseFlag = channel.get(); - boolean inUse = false; - if ( (inUseFlag & Record.IN_USE.byteValue()) == Record.IN_USE.byteValue() ) - { - inUse = true; - } - else if ( inUseFlag != Record.NOT_IN_USE.byteValue() ) - { - throw new IOException( "Illegal in use flag: " + inUseFlag ); - } - LabelTokenRecord record = new LabelTokenRecord( id ); - record.setInUse( inUse ); - record.setNameId( channel.getInt() ); - int nrTypeRecords = channel.getInt(); - for ( int i = 0; i < nrTypeRecords; i++ ) - { - DynamicRecord dr = readDynamicRecord( channel ); - if ( dr == null ) - { - return null; - } - record.addNameRecord( dr ); - } - return new Command.LabelTokenCommand( null, record ); - } - - private Command visitPropertyKeyTokenCommand( ReadableChannel channel ) throws IOException - { - // id+in_use(byte)+count(int)+key_blockId(int) - int id = channel.getInt(); - byte inUseFlag = channel.get(); - boolean inUse = false; - if ( (inUseFlag & Record.IN_USE.byteValue()) == Record.IN_USE.byteValue() ) - { - inUse = true; - } - else if ( inUseFlag != Record.NOT_IN_USE.byteValue() ) - { - throw new IOException( "Illegal in use flag: " + inUseFlag ); - } - PropertyKeyTokenRecord record = new PropertyKeyTokenRecord( id ); - record.setInUse( inUse ); - record.setPropertyCount( channel.getInt() ); - record.setNameId( channel.getInt() ); - int recordNr = readDynamicRecords( channel, record, PROPERTY_INDEX_DYNAMIC_RECORD_ADDER ); - if ( recordNr == -1 ) - { - return null; - } - return new Command.PropertyKeyTokenCommand( null, record ); - } - - private Command visitSchemaRuleCommand( ReadableChannel channel ) throws IOException - { - Collection recordsBefore = new ArrayList<>(); - readDynamicRecords( channel, recordsBefore, COLLECTION_DYNAMIC_RECORD_ADDER ); - Collection recordsAfter = new ArrayList<>(); - readDynamicRecords( channel, recordsAfter, COLLECTION_DYNAMIC_RECORD_ADDER ); - byte isCreated = channel.get(); - if ( 1 == isCreated ) - { - for ( DynamicRecord record : recordsAfter ) - { - record.setCreated(); - } - } - // read and ignore transaction id which is not used anymore - channel.getLong(); - SchemaRule rule = - Iterables.first( recordsAfter ).inUse() ? readSchemaRule( recordsAfter ) : readSchemaRule( recordsBefore ); - return new Command.SchemaRuleCommand( recordsBefore, recordsAfter, rule ); - } - - private Command visitNeoStoreCommand( ReadableChannel channel ) throws IOException - { - long nextProp = channel.getLong(); - NeoStoreRecord record = new NeoStoreRecord(); - record.setNextProp( nextProp ); - return new Command.NeoStoreCommand( null, record ); - } - - private NodeRecord readNodeRecord( long id, ReadableChannel channel ) throws IOException - { - byte inUseFlag = channel.get(); - boolean inUse = false; - if ( inUseFlag == Record.IN_USE.byteValue() ) - { - inUse = true; - } - else if ( inUseFlag != Record.NOT_IN_USE.byteValue() ) - { - throw new IOException( "Illegal in use flag: " + inUseFlag ); - } - NodeRecord record; - if ( inUse ) - { - record = new NodeRecord( id, false, channel.getLong(), channel.getLong() ); - // labels - long labelField = channel.getLong(); - Collection dynamicLabelRecords = new ArrayList<>(); - readDynamicRecords( channel, dynamicLabelRecords, COLLECTION_DYNAMIC_RECORD_ADDER ); - record.setLabelField( labelField, dynamicLabelRecords ); - } - else - { - record = new NodeRecord( id ); - } - record.setInUse( inUse ); - return record; - } - - private DynamicRecord readDynamicRecord( ReadableChannel channel ) throws IOException - { - // id+type+in_use(byte)+nr_of_bytes(int)+next_block(long) - long id = channel.getLong(); - assert id >= 0 && id <= (1L << 36) - 1 : id + " is not a valid dynamic record id"; - int type = channel.getInt(); - byte inUseFlag = channel.get(); - boolean inUse = (inUseFlag & Record.IN_USE.byteValue()) != 0; - DynamicRecord record = new DynamicRecord( id ); - record.setInUse( inUse, type ); - if ( inUse ) - { - record.setStartRecord( (inUseFlag & Record.FIRST_IN_CHAIN.byteValue()) != 0 ); - int nrOfBytes = channel.getInt(); - assert nrOfBytes >= 0 && nrOfBytes < ((1 << 24) - 1) : nrOfBytes - + " is not valid for a number of bytes field of " + "a dynamic record"; - long nextBlock = channel.getLong(); - assert (nextBlock >= 0 && nextBlock <= (1L << 36 - 1)) - || (nextBlock == Record.NO_NEXT_BLOCK.intValue()) : nextBlock - + " is not valid for a next record field of " + "a dynamic record"; - record.setNextBlock( nextBlock ); - byte[] data = new byte[nrOfBytes]; - channel.get( data, nrOfBytes ); - record.setData( data ); - } - return record; - } - - private int readDynamicRecords( ReadableChannel channel, T target, DynamicRecordAdder adder ) - throws IOException - { - final int numberOfRecords = channel.getInt(); - assert numberOfRecords >= 0; - int records = numberOfRecords; - while ( records-- > 0 ) - { - DynamicRecord read = readDynamicRecord( channel ); - if ( read == null ) - { - return -1; - } - adder.add( target, read ); - } - return numberOfRecords; - } - - private PropertyRecord readPropertyRecord( long id, ReadableChannel channel ) throws IOException - { - // in_use(byte)+type(int)+key_indexId(int)+prop_blockId(long)+ - // prev_prop_id(long)+next_prop_id(long) - PropertyRecord record = new PropertyRecord( id ); - byte inUseFlag = channel.get(); // 1 - long nextProp = channel.getLong(); // 8 - long prevProp = channel.getLong(); // 8 - record.setNextProp( nextProp ); - record.setPrevProp( prevProp ); - boolean inUse = false; - if ( (inUseFlag & Record.IN_USE.byteValue()) == Record.IN_USE.byteValue() ) - { - inUse = true; - } - boolean nodeProperty = true; - if ( (inUseFlag & Record.REL_PROPERTY.byteValue()) == Record.REL_PROPERTY.byteValue() ) - { - nodeProperty = false; - } - long primitiveId = channel.getLong(); // 8 - if ( primitiveId != -1 && nodeProperty ) - { - record.setNodeId( primitiveId ); - } - else if ( primitiveId != -1 ) - { - record.setRelId( primitiveId ); - } - int nrPropBlocks = channel.get(); - assert nrPropBlocks >= 0; - if ( nrPropBlocks > 0 ) - { - record.setInUse( true ); - } - while ( nrPropBlocks-- > 0 ) - { - PropertyBlock block = readPropertyBlock( channel ); - if ( block == null ) - { - return null; - } - record.addPropertyBlock( block ); - } - if ( readDynamicRecords( channel, record, PROPERTY_DELETED_DYNAMIC_RECORD_ADDER ) == -1 ) - { - return null; - } - if ( (inUse && !record.inUse()) || (!inUse && record.inUse()) ) - { - throw new IllegalStateException( "Weird, inUse was read in as " + inUse + " but the record is " + record ); - } - return record; - } - - private PropertyBlock readPropertyBlock( ReadableChannel channel ) throws IOException - { - PropertyBlock toReturn = new PropertyBlock(); - byte blockSize = channel.get(); // the size is stored in bytes // 1 - assert blockSize > 0 && blockSize % 8 == 0 : blockSize + " is not a valid block size value"; - // Read in blocks - long[] blocks = readLongs( channel, blockSize / 8 ); - assert blocks.length == blockSize / 8 : blocks.length - + " longs were read in while i asked for what corresponds to " + blockSize; - assert PropertyType.getPropertyTypeOrThrow( blocks[0] ).calculateNumberOfBlocksUsed( - blocks[0] ) == blocks.length : blocks.length + " is not a valid number of blocks for type " - + PropertyType.getPropertyTypeOrThrow( blocks[0] ); - /* - * Ok, now we may be ready to return, if there are no DynamicRecords. So - * we start building the Object - */ - toReturn.setValueBlocks( blocks ); - /* - * Read in existence of DynamicRecords. Remember, this has already been - * read in the buffer with the blocks, above. - */ - if ( readDynamicRecords( channel, toReturn, PROPERTY_BLOCK_DYNAMIC_RECORD_ADDER ) == -1 ) - { - return null; - } - return toReturn; - } - - private long[] readLongs( ReadableChannel channel, int count ) throws IOException - { - long[] result = new long[count]; - for ( int i = 0; i < count; i++ ) - { - result[i] = channel.getLong(); - } - return result; - } - - private SchemaRule readSchemaRule( Collection recordsBefore ) - { - assert Iterables.first( recordsBefore ).inUse() : "Asked to deserialize schema records that were not in use."; - SchemaRule rule; - ByteBuffer deserialized = AbstractDynamicStore.concatData( recordsBefore, new byte[100] ); - try - { - rule = SchemaRuleSerialization.deserialize( Iterables.first( recordsBefore ).getId(), deserialized ); - } - catch ( MalformedSchemaRuleException e ) - { - // TODO This is bad. We should probably just shut down if that happens - throw launderedException( e ); - } - return rule; - } -} diff --git a/community/kernel/src/main/java/org/neo4j/kernel/impl/transaction/command/PhysicalLogCommandReaderV2_1.java b/community/kernel/src/main/java/org/neo4j/kernel/impl/transaction/command/PhysicalLogCommandReaderV2_1.java deleted file mode 100644 index 224f63fec552f..0000000000000 --- a/community/kernel/src/main/java/org/neo4j/kernel/impl/transaction/command/PhysicalLogCommandReaderV2_1.java +++ /dev/null @@ -1,485 +0,0 @@ -/* - * Copyright (c) 2002-2017 "Neo Technology," - * Network Engine for Objects in Lund AB [http://neotechnology.com] - * - * This file is part of Neo4j. - * - * Neo4j is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ -package org.neo4j.kernel.impl.transaction.command; - -import java.io.IOException; -import java.nio.ByteBuffer; -import java.util.ArrayList; -import java.util.Collection; - -import org.neo4j.helpers.collection.Iterables; -import org.neo4j.kernel.api.exceptions.schema.MalformedSchemaRuleException; -import org.neo4j.kernel.impl.store.AbstractDynamicStore; -import org.neo4j.kernel.impl.store.PropertyType; -import org.neo4j.kernel.impl.store.record.DynamicRecord; -import org.neo4j.kernel.impl.store.record.LabelTokenRecord; -import org.neo4j.kernel.impl.store.record.NeoStoreRecord; -import org.neo4j.kernel.impl.store.record.NodeRecord; -import org.neo4j.kernel.impl.store.record.PropertyBlock; -import org.neo4j.kernel.impl.store.record.PropertyKeyTokenRecord; -import org.neo4j.kernel.impl.store.record.PropertyRecord; -import org.neo4j.kernel.impl.store.record.Record; -import org.neo4j.kernel.impl.store.record.RelationshipGroupRecord; -import org.neo4j.kernel.impl.store.record.RelationshipRecord; -import org.neo4j.kernel.impl.store.record.RelationshipTypeTokenRecord; -import org.neo4j.kernel.impl.store.record.SchemaRuleSerialization; -import org.neo4j.kernel.impl.transaction.command.CommandReading.DynamicRecordAdder; -import org.neo4j.storageengine.api.ReadableChannel; -import org.neo4j.storageengine.api.schema.SchemaRule; - -import static org.neo4j.helpers.Numbers.unsignedShortToInt; -import static org.neo4j.kernel.impl.transaction.command.CommandReading.COLLECTION_DYNAMIC_RECORD_ADDER; -import static org.neo4j.kernel.impl.transaction.command.CommandReading.PROPERTY_BLOCK_DYNAMIC_RECORD_ADDER; -import static org.neo4j.kernel.impl.transaction.command.CommandReading.PROPERTY_DELETED_DYNAMIC_RECORD_ADDER; -import static org.neo4j.kernel.impl.transaction.command.CommandReading.PROPERTY_INDEX_DYNAMIC_RECORD_ADDER; -import static org.neo4j.kernel.impl.util.Bits.bitFlag; -import static org.neo4j.kernel.impl.util.Bits.notFlag; - -public class PhysicalLogCommandReaderV2_1 extends BaseCommandReader -{ - @Override - protected Command read( byte commandType, ReadableChannel channel ) throws IOException - { - switch ( commandType ) - { - case NeoCommandType.NODE_COMMAND: - return visitNodeCommand( channel ); - case NeoCommandType.PROP_COMMAND: - return visitPropertyCommand( channel ); - case NeoCommandType.PROP_INDEX_COMMAND: - return visitPropertyKeyTokenCommand( channel ); - case NeoCommandType.REL_COMMAND: - return visitRelationshipCommand( channel ); - case NeoCommandType.REL_TYPE_COMMAND: - return visitRelationshipTypeTokenCommand( channel ); - case NeoCommandType.LABEL_KEY_COMMAND: - return visitLabelTokenCommand( channel ); - case NeoCommandType.NEOSTORE_COMMAND: - return visitNeoStoreCommand( channel ); - case NeoCommandType.SCHEMA_RULE_COMMAND: - return visitSchemaRuleCommand( channel ); - case NeoCommandType.REL_GROUP_COMMAND: - return visitRelationshipGroupCommand( channel ); - default: - throw unknownCommandType( commandType, channel ); - } - } - - private Command visitNodeCommand( ReadableChannel channel ) throws IOException - { - long id = channel.getLong(); - NodeRecord before = readNodeRecord( id, channel ); - if ( before == null ) - { - return null; - } - NodeRecord after = readNodeRecord( id, channel ); - if ( after == null ) - { - return null; - } - if ( !before.inUse() && after.inUse() ) - { - after.setCreated(); - } - return new Command.NodeCommand( before, after ); - } - - private Command visitRelationshipCommand( ReadableChannel channel ) throws IOException - { - long id = channel.getLong(); - byte flags = channel.get(); - boolean inUse = false; - if ( notFlag( notFlag( flags, Record.IN_USE.byteValue() ), Record.CREATED_IN_TX ) != 0 ) - { - throw new IOException( "Illegal in use flag: " + flags ); - } - if ( bitFlag( flags, Record.IN_USE.byteValue() ) ) - { - inUse = true; - } - RelationshipRecord record; - if ( inUse ) - { - record = new RelationshipRecord( id, channel.getLong(), channel.getLong(), channel.getInt() ); - record.setInUse( true ); - record.setFirstPrevRel( channel.getLong() ); - record.setFirstNextRel( channel.getLong() ); - record.setSecondPrevRel( channel.getLong() ); - record.setSecondNextRel( channel.getLong() ); - record.setNextProp( channel.getLong() ); - byte extraByte = channel.get(); - record.setFirstInFirstChain( (extraByte & 0x1) > 0 ); - record.setFirstInSecondChain( (extraByte & 0x2) > 0 ); - } - else - { - record = new RelationshipRecord( id ); - record.setInUse( false ); - } - if ( bitFlag( flags, Record.CREATED_IN_TX ) ) - { - record.setCreated(); - } - return new Command.RelationshipCommand( null, record ); - } - - private Command visitPropertyCommand( ReadableChannel channel ) throws IOException - { - // ID - long id = channel.getLong(); // 8 - // BEFORE - PropertyRecord before = readPropertyRecord( id, channel ); - if ( before == null ) - { - return null; - } - // AFTER - PropertyRecord after = readPropertyRecord( id, channel ); - if ( after == null ) - { - return null; - } - return new Command.PropertyCommand( before, after ); - } - - private Command visitRelationshipGroupCommand( ReadableChannel channel ) throws IOException - { - long id = channel.getLong(); - byte inUseByte = channel.get(); - boolean inUse = inUseByte == Record.IN_USE.byteValue(); - if ( inUseByte != Record.IN_USE.byteValue() && inUseByte != Record.NOT_IN_USE.byteValue() ) - { - throw new IOException( "Illegal in use flag: " + inUseByte ); - } - int type = unsignedShortToInt( channel.getShort() ); - RelationshipGroupRecord record = new RelationshipGroupRecord( id, type ); - record.setInUse( inUse ); - record.setNext( channel.getLong() ); - record.setFirstOut( channel.getLong() ); - record.setFirstIn( channel.getLong() ); - record.setFirstLoop( channel.getLong() ); - record.setOwningNode( channel.getLong() ); - - return new Command.RelationshipGroupCommand( null, record ); - } - - private Command visitRelationshipTypeTokenCommand( ReadableChannel channel ) throws IOException - { - // id+in_use(byte)+type_blockId(int)+nr_type_records(int) - int id = channel.getInt(); - byte inUseFlag = channel.get(); - boolean inUse = false; - if ( (inUseFlag & Record.IN_USE.byteValue()) == Record.IN_USE.byteValue() ) - { - inUse = true; - } - else if ( inUseFlag != Record.NOT_IN_USE.byteValue() ) - { - throw new IOException( "Illegal in use flag: " + inUseFlag ); - } - RelationshipTypeTokenRecord record = new RelationshipTypeTokenRecord( id ); - record.setInUse( inUse ); - record.setNameId( channel.getInt() ); - int nrTypeRecords = channel.getInt(); - for ( int i = 0; i < nrTypeRecords; i++ ) - { - DynamicRecord dr = readDynamicRecord( channel ); - if ( dr == null ) - { - return null; - } - record.addNameRecord( dr ); - } - return new Command.RelationshipTypeTokenCommand( null, record ); - } - - private Command visitLabelTokenCommand( ReadableChannel channel ) throws IOException - { - // id+in_use(byte)+type_blockId(int)+nr_type_records(int) - int id = channel.getInt(); - byte inUseFlag = channel.get(); - boolean inUse = false; - if ( (inUseFlag & Record.IN_USE.byteValue()) == Record.IN_USE.byteValue() ) - { - inUse = true; - } - else if ( inUseFlag != Record.NOT_IN_USE.byteValue() ) - { - throw new IOException( "Illegal in use flag: " + inUseFlag ); - } - LabelTokenRecord record = new LabelTokenRecord( id ); - record.setInUse( inUse ); - record.setNameId( channel.getInt() ); - int nrTypeRecords = channel.getInt(); - for ( int i = 0; i < nrTypeRecords; i++ ) - { - DynamicRecord dr = readDynamicRecord( channel ); - if ( dr == null ) - { - return null; - } - record.addNameRecord( dr ); - } - return new Command.LabelTokenCommand( null, record ); - } - - private Command visitPropertyKeyTokenCommand( ReadableChannel channel ) throws IOException - { - // id+in_use(byte)+count(int)+key_blockId(int) - int id = channel.getInt(); - byte inUseFlag = channel.get(); - boolean inUse = false; - if ( (inUseFlag & Record.IN_USE.byteValue()) == Record.IN_USE.byteValue() ) - { - inUse = true; - } - else if ( inUseFlag != Record.NOT_IN_USE.byteValue() ) - { - throw new IOException( "Illegal in use flag: " + inUseFlag ); - } - PropertyKeyTokenRecord record = new PropertyKeyTokenRecord( id ); - record.setInUse( inUse ); - record.setPropertyCount( channel.getInt() ); - record.setNameId( channel.getInt() ); - if ( readDynamicRecords( channel, record, PROPERTY_INDEX_DYNAMIC_RECORD_ADDER ) == -1 ) - { - return null; - } - return new Command.PropertyKeyTokenCommand( null, record ); - } - - private Command visitSchemaRuleCommand( ReadableChannel channel ) throws IOException - { - - Collection recordsBefore = new ArrayList<>(); - readDynamicRecords( channel, recordsBefore, COLLECTION_DYNAMIC_RECORD_ADDER ); - Collection recordsAfter = new ArrayList<>(); - readDynamicRecords( channel, recordsAfter, COLLECTION_DYNAMIC_RECORD_ADDER ); - byte isCreated = channel.get(); - if ( 1 == isCreated ) - { - for ( DynamicRecord record : recordsAfter ) - { - record.setCreated(); - } - } - channel.getLong(); // txId - ignored - SchemaRule rule = - Iterables.first( recordsAfter ).inUse() ? readSchemaRule( recordsAfter ) : readSchemaRule( recordsBefore ); - return new Command.SchemaRuleCommand( recordsBefore, recordsAfter, rule ); - } - - private Command visitNeoStoreCommand( ReadableChannel channel ) throws IOException - { - long nextProp = channel.getLong(); - NeoStoreRecord record = new NeoStoreRecord(); - record.setNextProp( nextProp ); - return new Command.NeoStoreCommand( null, record ); - } - - private NodeRecord readNodeRecord( long id, ReadableChannel channel ) throws IOException - { - byte inUseFlag = channel.get(); - boolean inUse = false; - if ( inUseFlag == Record.IN_USE.byteValue() ) - { - inUse = true; - } - else if ( inUseFlag != Record.NOT_IN_USE.byteValue() ) - { - throw new IOException( "Illegal in use flag: " + inUseFlag ); - } - NodeRecord record; - if ( inUse ) - { - boolean dense = channel.get() == 1; - record = new NodeRecord( id, dense, channel.getLong(), channel.getLong() ); - // labels - long labelField = channel.getLong(); - Collection dynamicLabelRecords = new ArrayList<>(); - readDynamicRecords( channel, dynamicLabelRecords, COLLECTION_DYNAMIC_RECORD_ADDER ); - record.setLabelField( labelField, dynamicLabelRecords ); - } - else - { - record = new NodeRecord( id ); - } - record.setInUse( inUse ); - return record; - } - - private DynamicRecord readDynamicRecord( ReadableChannel channel ) throws IOException - { - // id+type+in_use(byte)+nr_of_bytes(int)+next_block(long) - long id = channel.getLong(); - assert id >= 0 && id <= (1L << 36) - 1 : id + " is not a valid dynamic record id"; - int type = channel.getInt(); - byte inUseFlag = channel.get(); - boolean inUse = (inUseFlag & Record.IN_USE.byteValue()) != 0; - DynamicRecord record = new DynamicRecord( id ); - record.setInUse( inUse, type ); - if ( inUse ) - { - record.setStartRecord( (inUseFlag & Record.FIRST_IN_CHAIN.byteValue()) != 0 ); - int nrOfBytes = channel.getInt(); - assert nrOfBytes >= 0 && nrOfBytes < ((1 << 24) - 1) : nrOfBytes - + " is not valid for a number of bytes field of " + "a dynamic record"; - long nextBlock = channel.getLong(); - assert (nextBlock >= 0 && nextBlock <= (1L << 36 - 1)) - || (nextBlock == Record.NO_NEXT_BLOCK.intValue()) : nextBlock - + " is not valid for a next record field of " + "a dynamic record"; - record.setNextBlock( nextBlock ); - byte[] data = new byte[nrOfBytes]; - channel.get( data, nrOfBytes ); - record.setData( data ); - } - return record; - } - - private int readDynamicRecords( ReadableChannel channel, T target, DynamicRecordAdder adder ) - throws IOException - { - int numberOfRecords = channel.getInt(); - assert numberOfRecords >= 0; - for ( int i = numberOfRecords; i > 0; i-- ) - { - DynamicRecord read = readDynamicRecord( channel ); - if ( read == null ) - { - return -1; - } - adder.add( target, read ); - } - return numberOfRecords; - } - - private PropertyRecord readPropertyRecord( long id, ReadableChannel channel ) throws IOException - { - // in_use(byte)+type(int)+key_indexId(int)+prop_blockId(long)+ - // prev_prop_id(long)+next_prop_id(long) - PropertyRecord record = new PropertyRecord( id ); - byte inUseFlag = channel.get(); // 1 - long nextProp = channel.getLong(); // 8 - long prevProp = channel.getLong(); // 8 - record.setNextProp( nextProp ); - record.setPrevProp( prevProp ); - boolean inUse = false; - if ( (inUseFlag & Record.IN_USE.byteValue()) == Record.IN_USE.byteValue() ) - { - inUse = true; - } - boolean nodeProperty = true; - if ( (inUseFlag & Record.REL_PROPERTY.byteValue()) == Record.REL_PROPERTY.byteValue() ) - { - nodeProperty = false; - } - long primitiveId = channel.getLong(); // 8 - if ( primitiveId != -1 && nodeProperty ) - { - record.setNodeId( primitiveId ); - } - else if ( primitiveId != -1 ) - { - record.setRelId( primitiveId ); - } - int nrPropBlocks = channel.get(); - assert nrPropBlocks >= 0; - if ( nrPropBlocks > 0 ) - { - record.setInUse( true ); - } - while ( nrPropBlocks-- > 0 ) - { - PropertyBlock block = readPropertyBlock( channel ); - if ( block == null ) - { - return null; - } - record.addPropertyBlock( block ); - } - int deletedRecords = readDynamicRecords( channel, record, PROPERTY_DELETED_DYNAMIC_RECORD_ADDER ); - if ( deletedRecords == -1 ) - { - return null; - } - if ( (inUse && !record.inUse()) || (!inUse && record.inUse()) ) - { - throw new IllegalStateException( "Weird, inUse was read in as " + inUse + " but the record is " + record ); - } - return record; - } - - private PropertyBlock readPropertyBlock( ReadableChannel channel ) throws IOException - { - PropertyBlock toReturn = new PropertyBlock(); - byte blockSize = channel.get(); // the size is stored in bytes // 1 - assert blockSize > 0 && blockSize % 8 == 0 : blockSize + " is not a valid block size value"; - // Read in blocks - long[] blocks = readLongs( channel, blockSize / 8 ); - assert blocks.length == blockSize / 8 : blocks.length - + " longs were read in while i asked for what corresponds to " + blockSize; - assert PropertyType.getPropertyTypeOrThrow( blocks[0] ).calculateNumberOfBlocksUsed( - blocks[0] ) == blocks.length : blocks.length + " is not a valid number of blocks for type " - + PropertyType.getPropertyTypeOrThrow( blocks[0] ); - /* - * Ok, now we may be ready to return, if there are no DynamicRecords. So - * we start building the Object - */ - toReturn.setValueBlocks( blocks ); - /* - * Read in existence of DynamicRecords. Remember, this has already been - * read in the buffer with the blocks, above. - */ - if ( readDynamicRecords( channel, toReturn, PROPERTY_BLOCK_DYNAMIC_RECORD_ADDER ) == -1 ) - { - return null; - } - return toReturn; - } - - private long[] readLongs( ReadableChannel channel, int count ) throws IOException - { - long[] result = new long[count]; - for ( int i = 0; i < count; i++ ) - { - result[i] = channel.getLong(); - } - return result; - } - - private SchemaRule readSchemaRule( Collection recordsBefore ) - { - // TODO: Why was this assertion here? - // assert first(recordsBefore).inUse() : "Asked to deserialize schema records that were not in - // use."; - SchemaRule rule; - ByteBuffer deserialized = AbstractDynamicStore.concatData( recordsBefore, new byte[100] ); - try - { - rule = SchemaRuleSerialization.deserialize( Iterables.first( recordsBefore ).getId(), deserialized ); - } - catch ( MalformedSchemaRuleException e ) - { - return null; - } - return rule; - } -} diff --git a/community/kernel/src/main/java/org/neo4j/kernel/impl/transaction/command/PhysicalLogCommandReaderV2_2.java b/community/kernel/src/main/java/org/neo4j/kernel/impl/transaction/command/PhysicalLogCommandReaderV2_2.java deleted file mode 100644 index 27f06e76aae3e..0000000000000 --- a/community/kernel/src/main/java/org/neo4j/kernel/impl/transaction/command/PhysicalLogCommandReaderV2_2.java +++ /dev/null @@ -1,678 +0,0 @@ -/* - * Copyright (c) 2002-2017 "Neo Technology," - * Network Engine for Objects in Lund AB [http://neotechnology.com] - * - * This file is part of Neo4j. - * - * Neo4j is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ -package org.neo4j.kernel.impl.transaction.command; - -import java.io.IOException; -import java.nio.ByteBuffer; -import java.util.ArrayList; -import java.util.Collection; -import java.util.HashMap; -import java.util.Map; - -import org.neo4j.helpers.collection.Iterables; -import org.neo4j.kernel.api.exceptions.schema.MalformedSchemaRuleException; -import org.neo4j.kernel.impl.index.IndexCommand; -import org.neo4j.kernel.impl.index.IndexCommand.AddNodeCommand; -import org.neo4j.kernel.impl.index.IndexCommand.AddRelationshipCommand; -import org.neo4j.kernel.impl.index.IndexCommand.CreateCommand; -import org.neo4j.kernel.impl.index.IndexCommand.DeleteCommand; -import org.neo4j.kernel.impl.index.IndexCommand.RemoveCommand; -import org.neo4j.kernel.impl.index.IndexDefineCommand; -import org.neo4j.kernel.impl.store.AbstractDynamicStore; -import org.neo4j.kernel.impl.store.PropertyType; -import org.neo4j.kernel.impl.store.record.DynamicRecord; -import org.neo4j.kernel.impl.store.record.LabelTokenRecord; -import org.neo4j.kernel.impl.store.record.NeoStoreRecord; -import org.neo4j.kernel.impl.store.record.NodeRecord; -import org.neo4j.kernel.impl.store.record.PropertyBlock; -import org.neo4j.kernel.impl.store.record.PropertyKeyTokenRecord; -import org.neo4j.kernel.impl.store.record.PropertyRecord; -import org.neo4j.kernel.impl.store.record.Record; -import org.neo4j.kernel.impl.store.record.RelationshipGroupRecord; -import org.neo4j.kernel.impl.store.record.RelationshipRecord; -import org.neo4j.kernel.impl.store.record.RelationshipTypeTokenRecord; -import org.neo4j.kernel.impl.store.record.SchemaRuleSerialization; -import org.neo4j.kernel.impl.transaction.command.CommandReading.DynamicRecordAdder; -import org.neo4j.storageengine.api.ReadableChannel; -import org.neo4j.storageengine.api.schema.SchemaRule; - -import static org.neo4j.helpers.Numbers.unsignedShortToInt; -import static org.neo4j.kernel.impl.transaction.command.CommandReading.COLLECTION_DYNAMIC_RECORD_ADDER; -import static org.neo4j.kernel.impl.transaction.command.CommandReading.PROPERTY_BLOCK_DYNAMIC_RECORD_ADDER; -import static org.neo4j.kernel.impl.transaction.command.CommandReading.PROPERTY_DELETED_DYNAMIC_RECORD_ADDER; -import static org.neo4j.kernel.impl.transaction.command.CommandReading.PROPERTY_INDEX_DYNAMIC_RECORD_ADDER; -import static org.neo4j.kernel.impl.util.Bits.bitFlag; -import static org.neo4j.kernel.impl.util.Bits.notFlag; -import static org.neo4j.kernel.impl.util.IoPrimitiveUtils.read2bLengthAndString; -import static org.neo4j.kernel.impl.util.IoPrimitiveUtils.read2bMap; -import static org.neo4j.kernel.impl.util.IoPrimitiveUtils.read3bLengthAndString; - -public class PhysicalLogCommandReaderV2_2 extends BaseCommandReader -{ - @Override - protected Command read( byte commandType, ReadableChannel channel ) throws IOException - { - switch ( commandType ) - { - case NeoCommandType.NODE_COMMAND: - return visitNodeCommand( channel ); - case NeoCommandType.PROP_COMMAND: - return visitPropertyCommand( channel ); - case NeoCommandType.PROP_INDEX_COMMAND: - return visitPropertyKeyTokenCommand( channel ); - case NeoCommandType.REL_COMMAND: - return visitRelationshipCommand( channel ); - case NeoCommandType.REL_TYPE_COMMAND: - return visitRelationshipTypeTokenCommand( channel ); - case NeoCommandType.LABEL_KEY_COMMAND: - return visitLabelTokenCommand( channel ); - case NeoCommandType.NEOSTORE_COMMAND: - return visitNeoStoreCommand( channel ); - case NeoCommandType.SCHEMA_RULE_COMMAND: - return visitSchemaRuleCommand( channel ); - case NeoCommandType.REL_GROUP_COMMAND: - return visitRelationshipGroupCommand( channel ); - case NeoCommandType.INDEX_DEFINE_COMMAND: - return visitIndexDefineCommand( channel ); - case NeoCommandType.INDEX_ADD_COMMAND: - return visitIndexAddNodeCommand( channel ); - case NeoCommandType.INDEX_ADD_RELATIONSHIP_COMMAND: - return visitIndexAddRelationshipCommand( channel ); - case NeoCommandType.INDEX_REMOVE_COMMAND: - return visitIndexRemoveCommand( channel ); - case NeoCommandType.INDEX_DELETE_COMMAND: - return visitIndexDeleteCommand( channel ); - case NeoCommandType.INDEX_CREATE_COMMAND: - return visitIndexCreateCommand( channel ); - case NeoCommandType.UPDATE_RELATIONSHIP_COUNTS_COMMAND: - return visitRelationshipCountsCommand( channel ); - case NeoCommandType.UPDATE_NODE_COUNTS_COMMAND: - return visitNodeCountsCommand( channel ); - default: - throw unknownCommandType( commandType, channel ); - } - } - - private static final class IndexCommandHeader - { - byte valueType; - byte entityType; - boolean entityIdNeedsLong; - byte indexNameId; - boolean startNodeNeedsLong; - boolean endNodeNeedsLong; - byte keyId; - - IndexCommandHeader( byte valueType, byte entityType, boolean entityIdNeedsLong, byte indexNameId, - boolean startNodeNeedsLong, boolean endNodeNeedsLong, byte keyId ) - { - this.valueType = valueType; - this.entityType = entityType; - this.entityIdNeedsLong = entityIdNeedsLong; - this.indexNameId = indexNameId; - this.startNodeNeedsLong = startNodeNeedsLong; - this.endNodeNeedsLong = endNodeNeedsLong; - this.keyId = keyId; - } - } - - private Command visitNodeCommand( ReadableChannel channel ) throws IOException - { - long id = channel.getLong(); - NodeRecord before = readNodeRecord( id, channel ); - if ( before == null ) - { - return null; - } - NodeRecord after = readNodeRecord( id, channel ); - if ( after == null ) - { - return null; - } - if ( !before.inUse() && after.inUse() ) - { - after.setCreated(); - } - return new Command.NodeCommand( before, after ); - } - - private Command visitRelationshipCommand( ReadableChannel channel ) throws IOException - { - long id = channel.getLong(); - byte flags = channel.get(); - boolean inUse = false; - if ( notFlag( notFlag( flags, Record.IN_USE.byteValue() ), Record.CREATED_IN_TX ) != 0 ) - { - throw new IOException( "Illegal in use flag: " + flags ); - } - if ( bitFlag( flags, Record.IN_USE.byteValue() ) ) - { - inUse = true; - } - RelationshipRecord record; - if ( inUse ) - { - record = new RelationshipRecord( id, channel.getLong(), channel.getLong(), channel.getInt() ); - record.setInUse( true ); - record.setFirstPrevRel( channel.getLong() ); - record.setFirstNextRel( channel.getLong() ); - record.setSecondPrevRel( channel.getLong() ); - record.setSecondNextRel( channel.getLong() ); - record.setNextProp( channel.getLong() ); - byte extraByte = channel.get(); - record.setFirstInFirstChain( (extraByte & 0x1) > 0 ); - record.setFirstInSecondChain( (extraByte & 0x2) > 0 ); - } - else - { - record = new RelationshipRecord( id, -1, -1, channel.getInt() ); - record.setInUse( false ); - } - if ( bitFlag( flags, Record.CREATED_IN_TX ) ) - { - record.setCreated(); - } - return new Command.RelationshipCommand( null, record ); - } - - private Command visitPropertyCommand( ReadableChannel channel ) throws IOException - { - // ID - long id = channel.getLong(); // 8 - // BEFORE - PropertyRecord before = readPropertyRecord( id, channel ); - if ( before == null ) - { - return null; - } - // AFTER - PropertyRecord after = readPropertyRecord( id, channel ); - if ( after == null ) - { - return null; - } - return new Command.PropertyCommand( before, after ); - } - - private Command visitRelationshipGroupCommand( ReadableChannel channel ) throws IOException - { - long id = channel.getLong(); - byte inUseByte = channel.get(); - boolean inUse = inUseByte == Record.IN_USE.byteValue(); - if ( inUseByte != Record.IN_USE.byteValue() && inUseByte != Record.NOT_IN_USE.byteValue() ) - { - throw new IOException( "Illegal in use flag: " + inUseByte ); - } - int type = unsignedShortToInt( channel.getShort() ); - RelationshipGroupRecord record = new RelationshipGroupRecord( id, type ); - record.setInUse( inUse ); - record.setNext( channel.getLong() ); - record.setFirstOut( channel.getLong() ); - record.setFirstIn( channel.getLong() ); - record.setFirstLoop( channel.getLong() ); - record.setOwningNode( channel.getLong() ); - - return new Command.RelationshipGroupCommand( null, record ); - } - - private Command visitRelationshipTypeTokenCommand( ReadableChannel channel ) throws IOException - { - // id+in_use(byte)+type_blockId(int)+nr_type_records(int) - int id = channel.getInt(); - byte inUseFlag = channel.get(); - boolean inUse = false; - if ( (inUseFlag & Record.IN_USE.byteValue()) == Record.IN_USE.byteValue() ) - { - inUse = true; - } - else if ( inUseFlag != Record.NOT_IN_USE.byteValue() ) - { - throw new IOException( "Illegal in use flag: " + inUseFlag ); - } - RelationshipTypeTokenRecord record = new RelationshipTypeTokenRecord( id ); - record.setInUse( inUse ); - record.setNameId( channel.getInt() ); - int nrTypeRecords = channel.getInt(); - for ( int i = 0; i < nrTypeRecords; i++ ) - { - DynamicRecord dr = readDynamicRecord( channel ); - if ( dr == null ) - { - return null; - } - record.addNameRecord( dr ); - } - return new Command.RelationshipTypeTokenCommand( null, record ); - } - - private Command visitLabelTokenCommand( ReadableChannel channel ) throws IOException - { - // id+in_use(byte)+type_blockId(int)+nr_type_records(int) - int id = channel.getInt(); - byte inUseFlag = channel.get(); - boolean inUse = false; - if ( (inUseFlag & Record.IN_USE.byteValue()) == Record.IN_USE.byteValue() ) - { - inUse = true; - } - else if ( inUseFlag != Record.NOT_IN_USE.byteValue() ) - { - throw new IOException( "Illegal in use flag: " + inUseFlag ); - } - LabelTokenRecord record = new LabelTokenRecord( id ); - record.setInUse( inUse ); - record.setNameId( channel.getInt() ); - int nrTypeRecords = channel.getInt(); - for ( int i = 0; i < nrTypeRecords; i++ ) - { - DynamicRecord dr = readDynamicRecord( channel ); - if ( dr == null ) - { - return null; - } - record.addNameRecord( dr ); - } - return new Command.LabelTokenCommand( null, record ); - } - - private Command visitPropertyKeyTokenCommand( ReadableChannel channel ) throws IOException - { - // id+in_use(byte)+count(int)+key_blockId(int) - int id = channel.getInt(); - byte inUseFlag = channel.get(); - boolean inUse = false; - if ( (inUseFlag & Record.IN_USE.byteValue()) == Record.IN_USE.byteValue() ) - { - inUse = true; - } - else if ( inUseFlag != Record.NOT_IN_USE.byteValue() ) - { - throw new IOException( "Illegal in use flag: " + inUseFlag ); - } - PropertyKeyTokenRecord record = new PropertyKeyTokenRecord( id ); - record.setInUse( inUse ); - record.setPropertyCount( channel.getInt() ); - record.setNameId( channel.getInt() ); - if ( readDynamicRecords( channel, record, PROPERTY_INDEX_DYNAMIC_RECORD_ADDER ) == -1 ) - { - return null; - } - return new Command.PropertyKeyTokenCommand( null, record ); - } - - private Command visitSchemaRuleCommand( ReadableChannel channel ) throws IOException - { - Collection recordsBefore = new ArrayList<>(); - readDynamicRecords( channel, recordsBefore, COLLECTION_DYNAMIC_RECORD_ADDER ); - Collection recordsAfter = new ArrayList<>(); - readDynamicRecords( channel, recordsAfter, COLLECTION_DYNAMIC_RECORD_ADDER ); - byte isCreated = channel.get(); - if ( 1 == isCreated ) - { - for ( DynamicRecord record : recordsAfter ) - { - record.setCreated(); - } - } - SchemaRule rule = Iterables.first( recordsAfter ).inUse() - ? readSchemaRule( recordsAfter ) - : readSchemaRule( recordsBefore ); - return new Command.SchemaRuleCommand( recordsBefore, recordsAfter, rule ); - } - - private Command visitNeoStoreCommand( ReadableChannel channel ) throws IOException - { - long nextProp = channel.getLong(); - NeoStoreRecord record = new NeoStoreRecord(); - record.setNextProp( nextProp ); - return new Command.NeoStoreCommand( null, record ); - } - - private NodeRecord readNodeRecord( long id, ReadableChannel channel ) throws IOException - { - byte inUseFlag = channel.get(); - boolean inUse = false; - if ( inUseFlag == Record.IN_USE.byteValue() ) - { - inUse = true; - } - else if ( inUseFlag != Record.NOT_IN_USE.byteValue() ) - { - throw new IOException( "Illegal in use flag: " + inUseFlag ); - } - NodeRecord record; - Collection dynamicLabelRecords = new ArrayList<>(); - long labelField = Record.NO_LABELS_FIELD.intValue(); - if ( inUse ) - { - boolean dense = channel.get() == 1; - record = new NodeRecord( id, dense, channel.getLong(), channel.getLong() ); - // labels - labelField = channel.getLong(); - } - else - { - record = new NodeRecord( id ); - } - readDynamicRecords( channel, dynamicLabelRecords, COLLECTION_DYNAMIC_RECORD_ADDER ); - record.setLabelField( labelField, dynamicLabelRecords ); - record.setInUse( inUse ); - return record; - } - - private DynamicRecord readDynamicRecord( ReadableChannel channel ) throws IOException - { - // id+type+in_use(byte)+nr_of_bytes(int)+next_block(long) - long id = channel.getLong(); - assert id >= 0 && id <= (1L << 36) - 1 : id + " is not a valid dynamic record id"; - int type = channel.getInt(); - byte inUseFlag = channel.get(); - boolean inUse = (inUseFlag & Record.IN_USE.byteValue()) != 0; - DynamicRecord record = new DynamicRecord( id ); - record.setInUse( inUse, type ); - if ( inUse ) - { - record.setStartRecord( (inUseFlag & Record.FIRST_IN_CHAIN.byteValue()) != 0 ); - int nrOfBytes = channel.getInt(); - assert nrOfBytes >= 0 && nrOfBytes < ((1 << 24) - 1) : nrOfBytes - + " is not valid for a number of bytes field of " + "a dynamic record"; - long nextBlock = channel.getLong(); - assert (nextBlock >= 0 && nextBlock <= (1L << 36 - 1)) - || (nextBlock == Record.NO_NEXT_BLOCK.intValue()) : nextBlock - + " is not valid for a next record field of " + "a dynamic record"; - record.setNextBlock( nextBlock ); - byte[] data = new byte[nrOfBytes]; - channel.get( data, nrOfBytes ); - record.setData( data ); - } - return record; - } - - private int readDynamicRecords( ReadableChannel channel, T target, DynamicRecordAdder adder ) - throws IOException - { - int numberOfRecords = channel.getInt(); - assert numberOfRecords >= 0; - while ( numberOfRecords > 0 ) - { - DynamicRecord read = readDynamicRecord( channel ); - if ( read == null ) - { - return -1; - } - adder.add( target, read ); - numberOfRecords--; - } - return numberOfRecords; - } - - private PropertyRecord readPropertyRecord( long id, ReadableChannel channel ) throws IOException - { - // in_use(byte)+type(int)+key_indexId(int)+prop_blockId(long)+ - // prev_prop_id(long)+next_prop_id(long) - PropertyRecord record = new PropertyRecord( id ); - byte inUseFlag = channel.get(); // 1 - long nextProp = channel.getLong(); // 8 - long prevProp = channel.getLong(); // 8 - record.setNextProp( nextProp ); - record.setPrevProp( prevProp ); - boolean inUse = false; - if ( (inUseFlag & Record.IN_USE.byteValue()) == Record.IN_USE.byteValue() ) - { - inUse = true; - } - boolean nodeProperty = true; - if ( (inUseFlag & Record.REL_PROPERTY.byteValue()) == Record.REL_PROPERTY.byteValue() ) - { - nodeProperty = false; - } - long primitiveId = channel.getLong(); // 8 - if ( primitiveId != -1 && nodeProperty ) - { - record.setNodeId( primitiveId ); - } - else if ( primitiveId != -1 ) - { - record.setRelId( primitiveId ); - } - int nrPropBlocks = channel.get(); - assert nrPropBlocks >= 0; - if ( nrPropBlocks > 0 ) - { - record.setInUse( true ); - } - while ( nrPropBlocks-- > 0 ) - { - PropertyBlock block = readPropertyBlock( channel ); - if ( block == null ) - { - return null; - } - record.addPropertyBlock( block ); - } - int deletedRecords = readDynamicRecords( channel, record, PROPERTY_DELETED_DYNAMIC_RECORD_ADDER ); - if ( deletedRecords == -1 ) - { - return null; - } - assert deletedRecords >= 0; - while ( deletedRecords-- > 0 ) - { - DynamicRecord read = readDynamicRecord( channel ); - if ( read == null ) - { - return null; - } - record.addDeletedRecord( read ); - } - if ( (inUse && !record.inUse()) || (!inUse && record.inUse()) ) - { - throw new IllegalStateException( "Weird, inUse was read in as " + inUse + " but the record is " + record ); - } - return record; - } - - private PropertyBlock readPropertyBlock( ReadableChannel channel ) throws IOException - { - PropertyBlock toReturn = new PropertyBlock(); - byte blockSize = channel.get(); // the size is stored in bytes // 1 - assert blockSize > 0 && blockSize % 8 == 0 : blockSize + " is not a valid block size value"; - // Read in blocks - long[] blocks = readLongs( channel, blockSize / 8 ); - assert blocks.length == blockSize / 8 : blocks.length - + " longs were read in while i asked for what corresponds to " + blockSize; - assert PropertyType.getPropertyTypeOrThrow( blocks[0] ).calculateNumberOfBlocksUsed( - blocks[0] ) == blocks.length : blocks.length + " is not a valid number of blocks for type " - + PropertyType.getPropertyTypeOrThrow( blocks[0] ); - /* - * Ok, now we may be ready to return, if there are no DynamicRecords. So - * we start building the Object - */ - toReturn.setValueBlocks( blocks ); - /* - * Read in existence of DynamicRecords. Remember, this has already been - * read in the buffer with the blocks, above. - */ - if ( readDynamicRecords( channel, toReturn, PROPERTY_BLOCK_DYNAMIC_RECORD_ADDER ) == -1 ) - { - return null; - } - return toReturn; - } - - private long[] readLongs( ReadableChannel channel, int count ) throws IOException - { - long[] result = new long[count]; - for ( int i = 0; i < count; i++ ) - { - result[i] = channel.getLong(); - } - return result; - } - - private SchemaRule readSchemaRule( Collection recordsBefore ) - { - // TODO: Why was this assertion here? - // assert first(recordsBefore).inUse() : "Asked to deserialize schema records that were not in - // use."; - SchemaRule rule; - ByteBuffer deserialized = AbstractDynamicStore.concatData( recordsBefore, new byte[100] ); - try - { - rule = SchemaRuleSerialization.deserialize( Iterables.first( recordsBefore ).getId(), deserialized ); - } - catch ( MalformedSchemaRuleException e ) - { - return null; - } - return rule; - } - - private Command visitIndexAddNodeCommand( ReadableChannel channel ) throws IOException - { - IndexCommandHeader header = readIndexCommandHeader( channel ); - Number entityId = header.entityIdNeedsLong ? channel.getLong() : channel.getInt(); - Object value = readIndexValue( header.valueType, channel ); - AddNodeCommand command = new AddNodeCommand(); - command.init( header.indexNameId, entityId.longValue(), header.keyId, value ); - return command; - } - - private Command visitIndexAddRelationshipCommand( ReadableChannel channel ) throws IOException - { - IndexCommandHeader header = readIndexCommandHeader( channel ); - Number entityId = header.entityIdNeedsLong ? channel.getLong() : channel.getInt(); - Object value = readIndexValue( header.valueType, channel ); - Number startNode = header.startNodeNeedsLong ? channel.getLong() : channel.getInt(); - Number endNode = header.endNodeNeedsLong ? channel.getLong() : channel.getInt(); - AddRelationshipCommand command = new AddRelationshipCommand(); - command.init( header.indexNameId, entityId.longValue(), header.keyId, value, startNode.longValue(), - endNode.longValue() ); - return command; - } - - private Command visitIndexRemoveCommand( ReadableChannel channel ) throws IOException - { - IndexCommandHeader header = readIndexCommandHeader( channel ); - Number entityId = header.entityIdNeedsLong ? channel.getLong() : channel.getInt(); - Object value = readIndexValue( header.valueType, channel ); - RemoveCommand command = new RemoveCommand(); - command.init( header.indexNameId, header.entityType, entityId.longValue(), header.keyId, value ); - return command; - } - - private Command visitIndexDeleteCommand( ReadableChannel channel ) throws IOException - { - IndexCommandHeader header = readIndexCommandHeader( channel ); - DeleteCommand command = new DeleteCommand(); - command.init( header.indexNameId, header.entityType ); - return command; - } - - private Command visitIndexCreateCommand( ReadableChannel channel ) throws IOException - { - IndexCommandHeader header = readIndexCommandHeader( channel ); - Map config = read2bMap( channel ); - CreateCommand command = new CreateCommand(); - command.init( header.indexNameId, header.entityType, config ); - return command; - } - - private Command visitIndexDefineCommand( ReadableChannel channel ) throws IOException - { - readIndexCommandHeader( channel ); - Map indexNames = readMap( channel ); - Map keys = readMap( channel ); - IndexDefineCommand command = new IndexDefineCommand(); - command.init( indexNames, keys ); - return command; - } - - private Command visitNodeCountsCommand( ReadableChannel channel ) throws IOException - { - int labelId = channel.getInt(); - long delta = channel.getLong(); - return new Command.NodeCountsCommand( labelId, delta ); - } - - private Command visitRelationshipCountsCommand( ReadableChannel channel ) throws IOException - { - int startLabelId = channel.getInt(); - int typeId = channel.getInt(); - int endLabelId = channel.getInt(); - long delta = channel.getLong(); - return new Command.RelationshipCountsCommand( startLabelId, typeId, endLabelId, delta ); - } - - private Map readMap( ReadableChannel channel ) throws IOException - { - byte size = channel.get(); - Map result = new HashMap<>(); - for ( int i = 0; i < size; i++ ) - { - String key = read2bLengthAndString( channel ); - int id = channel.get(); - if ( key == null ) - { - return null; - } - result.put( key, id ); - } - return result; - } - - private IndexCommandHeader readIndexCommandHeader( ReadableChannel channel ) throws IOException - { - byte[] headerBytes = new byte[3]; - channel.get( headerBytes, headerBytes.length ); - byte valueType = (byte) ((headerBytes[0] & 0x1C) >> 2); - byte entityType = (byte) ((headerBytes[0] & 0x2) >> 1); - boolean entityIdNeedsLong = (headerBytes[0] & 0x1) > 0; - byte indexNameId = (byte) (headerBytes[1] & 0x3F); - boolean startNodeNeedsLong = (headerBytes[1] & 0x80) > 0; - boolean endNodeNeedsLong = (headerBytes[1] & 0x40) > 0; - byte keyId = headerBytes[2]; - return new IndexCommandHeader( valueType, entityType, entityIdNeedsLong, indexNameId, startNodeNeedsLong, - endNodeNeedsLong, keyId ); - } - - private Object readIndexValue( byte valueType, ReadableChannel channel ) throws IOException - { - switch ( valueType ) - { - case IndexCommand.VALUE_TYPE_NULL: - return null; - case IndexCommand.VALUE_TYPE_SHORT: - return channel.getShort(); - case IndexCommand.VALUE_TYPE_INT: - return channel.getInt(); - case IndexCommand.VALUE_TYPE_LONG: - return channel.getLong(); - case IndexCommand.VALUE_TYPE_FLOAT: - return channel.getFloat(); - case IndexCommand.VALUE_TYPE_DOUBLE: - return channel.getDouble(); - case IndexCommand.VALUE_TYPE_STRING: - return read3bLengthAndString( channel ); - default: - throw new RuntimeException( "Unknown value type " + valueType ); - } - } -} diff --git a/community/kernel/src/main/java/org/neo4j/kernel/impl/transaction/log/entry/IdentifiableLogEntry.java b/community/kernel/src/main/java/org/neo4j/kernel/impl/transaction/log/entry/IdentifiableLogEntry.java deleted file mode 100644 index 351aacf986111..0000000000000 --- a/community/kernel/src/main/java/org/neo4j/kernel/impl/transaction/log/entry/IdentifiableLogEntry.java +++ /dev/null @@ -1,87 +0,0 @@ -/* - * Copyright (c) 2002-2017 "Neo Technology," - * Network Engine for Objects in Lund AB [http://neotechnology.com] - * - * This file is part of Neo4j. - * - * Neo4j is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ -package org.neo4j.kernel.impl.transaction.log.entry; - -import java.util.TimeZone; - -/* - * This class is used when reading legacy log entries and it will preserve their identifiers. - * Identifiers will be use for reordering the log entries when migrating from older neo4j versions. - */ -public class IdentifiableLogEntry implements LogEntry -{ - private final LogEntry entry; - private final int identifier; - - public IdentifiableLogEntry( LogEntry entry, int identifier ) - { - this.entry = entry; - this.identifier = identifier; - } - - @Override - public byte getType() - { - return entry.getType(); - } - - @Override - public LogEntryVersion getVersion() - { - return entry.getVersion(); - } - - @Override - public String toString( TimeZone timeZone ) - { - return entry.toString( timeZone ); - } - - @Override - public String timestamp( long timeWritten, TimeZone timeZone ) - { - return entry.timestamp( timeWritten, timeZone ); - } - - @Override - public T as() - { - return (T) entry; - } - - public int getIdentifier() - { - return identifier; - } - - public LogEntry getEntry() - { - return entry; - } - - @Override - public String toString() - { - return "IdentifiableLogEntry{" + - "identifier=" + identifier + - ", entry=" + entry + - '}'; - } -} diff --git a/community/kernel/src/main/java/org/neo4j/kernel/impl/transaction/log/entry/LogEntryByteCodes.java b/community/kernel/src/main/java/org/neo4j/kernel/impl/transaction/log/entry/LogEntryByteCodes.java index 8a00011b85acc..dab403da86bd0 100644 --- a/community/kernel/src/main/java/org/neo4j/kernel/impl/transaction/log/entry/LogEntryByteCodes.java +++ b/community/kernel/src/main/java/org/neo4j/kernel/impl/transaction/log/entry/LogEntryByteCodes.java @@ -23,7 +23,7 @@ public class LogEntryByteCodes { private LogEntryByteCodes() { - // no instances are allowed + throw new AssertionError(); // no instances are allowed } // empty record due to memory mapped file @@ -31,10 +31,7 @@ private LogEntryByteCodes() // Real entries public static final byte TX_START = (byte) 1; - public static final byte TX_PREPARE = (byte) 2; public static final byte COMMAND = (byte) 3; - public static final byte DONE = (byte) 4; public static final byte TX_1P_COMMIT = (byte) 5; - public static final byte TX_2P_COMMIT = (byte) 6; public static final byte CHECK_POINT = (byte) 7; } diff --git a/community/kernel/src/main/java/org/neo4j/kernel/impl/transaction/log/entry/LogEntryCommand.java b/community/kernel/src/main/java/org/neo4j/kernel/impl/transaction/log/entry/LogEntryCommand.java index 5575c34f706e9..107efbcad626a 100644 --- a/community/kernel/src/main/java/org/neo4j/kernel/impl/transaction/log/entry/LogEntryCommand.java +++ b/community/kernel/src/main/java/org/neo4j/kernel/impl/transaction/log/entry/LogEntryCommand.java @@ -51,6 +51,7 @@ public String toString() } @Override + @SuppressWarnings( "unchecked" ) public T as() { return (T) this; diff --git a/community/kernel/src/main/java/org/neo4j/kernel/impl/transaction/log/entry/LogEntryParsersV2_0.java b/community/kernel/src/main/java/org/neo4j/kernel/impl/transaction/log/entry/LogEntryParsersV2_0.java deleted file mode 100644 index 360caa39a2014..0000000000000 --- a/community/kernel/src/main/java/org/neo4j/kernel/impl/transaction/log/entry/LogEntryParsersV2_0.java +++ /dev/null @@ -1,231 +0,0 @@ -/* - * Copyright (c) 2002-2017 "Neo Technology," - * Network Engine for Objects in Lund AB [http://neotechnology.com] - * - * This file is part of Neo4j. - * - * Neo4j is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ -package org.neo4j.kernel.impl.transaction.log.entry; - -import java.io.IOException; - -import org.neo4j.kernel.impl.transaction.log.LogPosition; -import org.neo4j.kernel.impl.transaction.log.LogPositionMarker; -import org.neo4j.kernel.impl.transaction.log.ReadableClosableChannel; -import org.neo4j.storageengine.api.CommandReaderFactory; -import org.neo4j.storageengine.api.StorageCommand; - -import static org.neo4j.kernel.impl.transaction.log.entry.LogEntryStart.EMPTY_ADDITIONAL_ARRAY; - -public enum LogEntryParsersV2_0 implements LogEntryParser -{ - EMPTY - { - @Override - public IdentifiableLogEntry parse( LogEntryVersion version, ReadableClosableChannel channel, - LogPositionMarker marker, CommandReaderFactory commandReader ) throws IOException - - { - return null; - } - - @Override - public byte byteCode() - { - return LogEntryByteCodes.EMPTY; - } - - @Override - public boolean skip() - { - return false; - } - }, - - TX_PREPARE - { - @Override - public IdentifiableLogEntry parse( LogEntryVersion version, ReadableClosableChannel channel, - LogPositionMarker marker, CommandReaderFactory commandReader ) throws IOException - - { - // we ignore this we do not this in the new log format, just parse data to be skipped in the - // channel - // ignored identifier - channel.getInt(); - // ignored timeWritten - channel.getLong(); - return null; - } - - @Override - public byte byteCode() - { - return LogEntryByteCodes.TX_PREPARE; - } - - @Override - public boolean skip() - { - return true; - } - }, - TX_START - { - @Override - public IdentifiableLogEntry parse( LogEntryVersion version, ReadableClosableChannel channel, - LogPositionMarker marker, CommandReaderFactory commandReader ) throws IOException - - { - LogPosition position = marker.newPosition(); - byte globalIdLength = channel.get(); - byte branchIdLength = channel.get(); - // ignored globalId - channel.get( new byte[globalIdLength], globalIdLength ); - // ignored branchId - channel.get( new byte[branchIdLength], branchIdLength ); - int identifier = channel.getInt(); - // ignored formatId - channel.getInt(); - - int masterId = channel.getInt(); - int authorId = channel.getInt(); - long timeWritten = channel.getLong(); - long latestCommittedTxWhenStarted = channel.getLong(); - - return new IdentifiableLogEntry( - new LogEntryStart( masterId, authorId, timeWritten, latestCommittedTxWhenStarted, - EMPTY_ADDITIONAL_ARRAY, position ), - identifier ); - } - - @Override - public byte byteCode() - { - return LogEntryByteCodes.TX_START; - } - - @Override - public boolean skip() - { - return false; - } - }, - COMMAND - { - @Override - public IdentifiableLogEntry parse( LogEntryVersion version, ReadableClosableChannel channel, - LogPositionMarker marker, CommandReaderFactory commandReader ) throws IOException - - { - int identifier = channel.getInt(); - StorageCommand command = commandReader.byVersion( version.byteCode() ).read( channel ); - return command == null - ? null - : new IdentifiableLogEntry( new LogEntryCommand( version, command ), identifier ); - } - - @Override - public byte byteCode() - { - return LogEntryByteCodes.COMMAND; - } - - @Override - public boolean skip() - { - return false; - } - }, - DONE - { - @Override - public IdentifiableLogEntry parse( LogEntryVersion version, ReadableClosableChannel channel, - LogPositionMarker marker, CommandReaderFactory commandReader ) throws IOException - - { - // we ignore this we do not this in the new log format, just parse data to be skipped in the - // channel - // ignored identifier - channel.getInt(); - return null; - } - - @Override - public byte byteCode() - { - return LogEntryByteCodes.DONE; - } - - @Override - public boolean skip() - { - return true; - } - }, - TX_1P_COMMIT - { - @Override - public IdentifiableLogEntry parse( LogEntryVersion version, ReadableClosableChannel channel, - LogPositionMarker marker, CommandReaderFactory commandReader ) throws IOException - - { - int identifier = channel.getInt(); - long txId = channel.getLong(); - long timeWritten = channel.getLong(); - return new IdentifiableLogEntry( new OnePhaseCommit( txId, timeWritten ), identifier ); - } - - @Override - public byte byteCode() - { - return LogEntryByteCodes.TX_1P_COMMIT; - } - - @Override - public boolean skip() - { - return false; - } - }, - TX_2P_COMMIT - { - @Override - public IdentifiableLogEntry parse( LogEntryVersion version, ReadableClosableChannel channel, - LogPositionMarker marker, CommandReaderFactory commandReader ) throws IOException - - { - int identifier = channel.getInt(); - long txId = channel.getLong(); - long timeWritten = channel.getLong(); - - // let's map the 2 phase commit into 1 phase commit since the 2 phase commits are gone - return new IdentifiableLogEntry( new OnePhaseCommit( txId, timeWritten ), identifier ); - } - - @Override - public byte byteCode() - { - return LogEntryByteCodes.TX_2P_COMMIT; - } - - @Override - public boolean skip() - { - return false; - } - } - -} diff --git a/community/kernel/src/main/java/org/neo4j/kernel/impl/transaction/log/entry/LogEntryParsersV2_1.java b/community/kernel/src/main/java/org/neo4j/kernel/impl/transaction/log/entry/LogEntryParsersV2_1.java deleted file mode 100644 index 182301bda99cc..0000000000000 --- a/community/kernel/src/main/java/org/neo4j/kernel/impl/transaction/log/entry/LogEntryParsersV2_1.java +++ /dev/null @@ -1,224 +0,0 @@ -/* - * Copyright (c) 2002-2017 "Neo Technology," - * Network Engine for Objects in Lund AB [http://neotechnology.com] - * - * This file is part of Neo4j. - * - * Neo4j is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ -package org.neo4j.kernel.impl.transaction.log.entry; - -import java.io.IOException; - -import org.neo4j.kernel.impl.transaction.log.LogPosition; -import org.neo4j.kernel.impl.transaction.log.LogPositionMarker; -import org.neo4j.kernel.impl.transaction.log.ReadableClosableChannel; -import org.neo4j.storageengine.api.CommandReaderFactory; -import org.neo4j.storageengine.api.StorageCommand; - -import static org.neo4j.kernel.impl.transaction.log.entry.LogEntryStart.EMPTY_ADDITIONAL_ARRAY; - -public enum LogEntryParsersV2_1 implements LogEntryParser -{ - EMPTY - { - @Override - public IdentifiableLogEntry parse( LogEntryVersion version, ReadableClosableChannel channel, - LogPositionMarker marker, CommandReaderFactory commandReader ) throws IOException - { - return null; - } - - @Override - public byte byteCode() - { - return LogEntryByteCodes.EMPTY; - } - - @Override - public boolean skip() - { - return false; - } - }, - - TX_PREPARE - { - @Override - public IdentifiableLogEntry parse( LogEntryVersion version, ReadableClosableChannel channel, - LogPositionMarker marker, CommandReaderFactory commandReader ) throws IOException - { - // we ignore this we do not this in the new log format, just parse data to be skipped in the - // channel - // ignored identifier - channel.getInt(); - // ignored timeWritten - channel.getLong(); - return null; - } - - @Override - public byte byteCode() - { - return LogEntryByteCodes.TX_PREPARE; - } - - @Override - public boolean skip() - { - return true; - } - }, - TX_START - { - @Override - public IdentifiableLogEntry parse( LogEntryVersion version, ReadableClosableChannel channel, - LogPositionMarker marker, CommandReaderFactory commandReader ) throws IOException - { - LogPosition position = marker.newPosition(); - byte globalIdLength = channel.get(); - byte branchIdLength = channel.get(); - // ignored globalId - channel.get( new byte[globalIdLength], globalIdLength ); - // ignored branchId - channel.get( new byte[branchIdLength], branchIdLength ); - int identifier = channel.getInt(); - // ignored formatId - channel.getInt(); - - int masterId = channel.getInt(); - int authorId = channel.getInt(); - long timeWritten = channel.getLong(); - long latestCommittedTxWhenStarted = channel.getLong(); - - return new IdentifiableLogEntry( - new LogEntryStart( masterId, authorId, timeWritten, latestCommittedTxWhenStarted, - EMPTY_ADDITIONAL_ARRAY, position ), - identifier ); - } - - @Override - public byte byteCode() - { - return LogEntryByteCodes.TX_START; - } - - @Override - public boolean skip() - { - return false; - } - }, - COMMAND - { - @Override - public IdentifiableLogEntry parse( LogEntryVersion version, ReadableClosableChannel channel, - LogPositionMarker marker, CommandReaderFactory commandReader ) throws IOException - { - int identifier = channel.getInt(); - StorageCommand command = commandReader.byVersion( version.byteCode() ).read( channel ); - return command == null - ? null - : new IdentifiableLogEntry( new LogEntryCommand( version, command ), identifier ); - } - - @Override - public byte byteCode() - { - return LogEntryByteCodes.COMMAND; - } - - @Override - public boolean skip() - { - return false; - } - }, - DONE - { - @Override - public IdentifiableLogEntry parse( LogEntryVersion version, ReadableClosableChannel channel, - LogPositionMarker marker, CommandReaderFactory commandReader ) throws IOException - { - // we ignore this we do not this in the new log format, just parse data to be skipped in the - // channel - // ignored identifier - channel.getInt(); - return null; - } - - @Override - public byte byteCode() - { - return LogEntryByteCodes.DONE; - } - - @Override - public boolean skip() - { - return true; - } - }, - TX_1P_COMMIT - { - @Override - public IdentifiableLogEntry parse( LogEntryVersion version, ReadableClosableChannel channel, - LogPositionMarker marker, CommandReaderFactory commandReader ) throws IOException - { - int identifier = channel.getInt(); - long txId = channel.getLong(); - long timeWritten = channel.getLong(); - return new IdentifiableLogEntry( new OnePhaseCommit( txId, timeWritten ), identifier ); - } - - @Override - public byte byteCode() - { - return LogEntryByteCodes.TX_1P_COMMIT; - } - - @Override - public boolean skip() - { - return false; - } - }, - TX_2P_COMMIT - { - @Override - public IdentifiableLogEntry parse( LogEntryVersion version, ReadableClosableChannel channel, - LogPositionMarker marker, CommandReaderFactory commandReader ) throws IOException - { - int identifier = channel.getInt(); - long txId = channel.getLong(); - long timeWritten = channel.getLong(); - - // let's map the 2 phase commit into 1 phase commit since the 2 phase commits are gone - return new IdentifiableLogEntry( new OnePhaseCommit( txId, timeWritten ), identifier ); - } - - @Override - public byte byteCode() - { - return LogEntryByteCodes.TX_2P_COMMIT; - } - - @Override - public boolean skip() - { - return false; - } - } - -} diff --git a/community/kernel/src/main/java/org/neo4j/kernel/impl/transaction/log/entry/LogEntryParsersV2_2.java b/community/kernel/src/main/java/org/neo4j/kernel/impl/transaction/log/entry/LogEntryParsersV2_2.java deleted file mode 100644 index b494c5de93aee..0000000000000 --- a/community/kernel/src/main/java/org/neo4j/kernel/impl/transaction/log/entry/LogEntryParsersV2_2.java +++ /dev/null @@ -1,133 +0,0 @@ -/* - * Copyright (c) 2002-2017 "Neo Technology," - * Network Engine for Objects in Lund AB [http://neotechnology.com] - * - * This file is part of Neo4j. - * - * Neo4j is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ -package org.neo4j.kernel.impl.transaction.log.entry; - -import java.io.IOException; - -import org.neo4j.kernel.impl.transaction.log.LogPosition; -import org.neo4j.kernel.impl.transaction.log.LogPositionMarker; -import org.neo4j.kernel.impl.transaction.log.ReadableClosableChannel; -import org.neo4j.storageengine.api.CommandReaderFactory; -import org.neo4j.storageengine.api.StorageCommand; - -public enum LogEntryParsersV2_2 implements LogEntryParser -{ - EMPTY - { - @Override - public LogEntry parse( LogEntryVersion version, ReadableClosableChannel channel, LogPositionMarker marker, - CommandReaderFactory commandReader ) throws IOException - { - return null; - - } - - @Override - public byte byteCode() - { - return LogEntryByteCodes.EMPTY; - } - - @Override - public boolean skip() - { - return false; - } - }, - - TX_START - { - @Override - public LogEntry parse( LogEntryVersion version, ReadableClosableChannel channel, LogPositionMarker marker, - CommandReaderFactory commandReader ) throws IOException - { - LogPosition position = marker.newPosition(); - int masterId = channel.getInt(); - int authorId = channel.getInt(); - long timeWritten = channel.getLong(); - long latestCommittedTxWhenStarted = channel.getLong(); - int additionalHeaderLength = channel.getInt(); - byte[] additionalHeader = new byte[additionalHeaderLength]; - channel.get( additionalHeader, additionalHeaderLength ); - return new LogEntryStart( version, masterId, authorId, timeWritten, - latestCommittedTxWhenStarted, - additionalHeader, position ); - } - - @Override - public byte byteCode() - { - return LogEntryByteCodes.TX_START; - } - - @Override - public boolean skip() - { - return false; - } - }, - - COMMAND - { - @Override - public LogEntry parse( LogEntryVersion version, ReadableClosableChannel channel, LogPositionMarker marker, - CommandReaderFactory commandReader ) throws IOException - { - StorageCommand command = commandReader.byVersion( version.byteCode() ).read( channel ); - return command == null ? null : new LogEntryCommand( version, command ); - } - - @Override - public byte byteCode() - { - return LogEntryByteCodes.COMMAND; - } - - @Override - public boolean skip() - { - return false; - } - }, - - TX_1P_COMMIT - { - @Override - public LogEntry parse( LogEntryVersion version, ReadableClosableChannel channel, LogPositionMarker marker, - CommandReaderFactory commandReader ) throws IOException - { - long txId = channel.getLong(); - long timeWritten = channel.getLong(); - return new OnePhaseCommit( version, txId, timeWritten ); - } - - @Override - public byte byteCode() - { - return LogEntryByteCodes.TX_1P_COMMIT; - } - - @Override - public boolean skip() - { - return false; - } - } -} diff --git a/community/kernel/src/main/java/org/neo4j/kernel/impl/transaction/log/entry/LogEntryParsersV2_2_4.java b/community/kernel/src/main/java/org/neo4j/kernel/impl/transaction/log/entry/LogEntryParsersV2_2_4.java deleted file mode 100644 index 47e28198dcf42..0000000000000 --- a/community/kernel/src/main/java/org/neo4j/kernel/impl/transaction/log/entry/LogEntryParsersV2_2_4.java +++ /dev/null @@ -1,133 +0,0 @@ -/* - * Copyright (c) 2002-2017 "Neo Technology," - * Network Engine for Objects in Lund AB [http://neotechnology.com] - * - * This file is part of Neo4j. - * - * Neo4j is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ -package org.neo4j.kernel.impl.transaction.log.entry; - -import java.io.IOException; - -import org.neo4j.kernel.impl.transaction.log.LogPosition; -import org.neo4j.kernel.impl.transaction.log.LogPositionMarker; -import org.neo4j.kernel.impl.transaction.log.ReadableClosableChannel; -import org.neo4j.storageengine.api.CommandReaderFactory; -import org.neo4j.storageengine.api.StorageCommand; - -public enum LogEntryParsersV2_2_4 implements LogEntryParser -{ - EMPTY - { - @Override - public LogEntry parse( LogEntryVersion version, ReadableClosableChannel channel, LogPositionMarker marker, - CommandReaderFactory commandReader ) throws IOException - { - return null; - - } - - @Override - public byte byteCode() - { - return LogEntryByteCodes.EMPTY; - } - - @Override - public boolean skip() - { - return false; - } - }, - - TX_START - { - @Override - public LogEntry parse( LogEntryVersion version, ReadableClosableChannel channel, LogPositionMarker marker, - CommandReaderFactory commandReader ) throws IOException - { - LogPosition position = marker.newPosition(); - int masterId = channel.getInt(); - int authorId = channel.getInt(); - long timeWritten = channel.getLong(); - long latestCommittedTxWhenStarted = channel.getLong(); - int additionalHeaderLength = channel.getInt(); - byte[] additionalHeader = new byte[additionalHeaderLength]; - channel.get( additionalHeader, additionalHeaderLength ); - return new LogEntryStart( version, masterId, authorId, timeWritten, - latestCommittedTxWhenStarted, - additionalHeader, position ); - } - - @Override - public byte byteCode() - { - return LogEntryByteCodes.TX_START; - } - - @Override - public boolean skip() - { - return false; - } - }, - - COMMAND - { - @Override - public LogEntry parse( LogEntryVersion version, ReadableClosableChannel channel, LogPositionMarker marker, - CommandReaderFactory commandReader ) throws IOException - { - StorageCommand command = commandReader.byVersion( version.byteCode() ).read( channel ); - return command == null ? null : new LogEntryCommand( version, command ); - } - - @Override - public byte byteCode() - { - return LogEntryByteCodes.COMMAND; - } - - @Override - public boolean skip() - { - return false; - } - }, - - TX_1P_COMMIT - { - @Override - public LogEntry parse( LogEntryVersion version, ReadableClosableChannel channel, LogPositionMarker marker, - CommandReaderFactory commandReader ) throws IOException - { - long txId = channel.getLong(); - long timeWritten = channel.getLong(); - return new OnePhaseCommit( version, txId, timeWritten ); - } - - @Override - public byte byteCode() - { - return LogEntryByteCodes.TX_1P_COMMIT; - } - - @Override - public boolean skip() - { - return false; - } - } -} diff --git a/community/kernel/src/main/java/org/neo4j/kernel/impl/transaction/log/entry/LogEntryParsersV2_3.java b/community/kernel/src/main/java/org/neo4j/kernel/impl/transaction/log/entry/LogEntryParsersV2_3.java index dc326d017c798..2a901dc6d52c2 100644 --- a/community/kernel/src/main/java/org/neo4j/kernel/impl/transaction/log/entry/LogEntryParsersV2_3.java +++ b/community/kernel/src/main/java/org/neo4j/kernel/impl/transaction/log/entry/LogEntryParsersV2_3.java @@ -36,7 +36,6 @@ public LogEntry parse( LogEntryVersion version, ReadableClosableChannel channel, CommandReaderFactory commandReader ) throws IOException { return null; - } @Override @@ -130,6 +129,7 @@ public boolean skip() return false; } }, + CHECK_POINT { @Override diff --git a/community/kernel/src/main/java/org/neo4j/kernel/impl/transaction/log/entry/LogEntrySanity.java b/community/kernel/src/main/java/org/neo4j/kernel/impl/transaction/log/entry/LogEntrySanity.java index 4712c714d041c..b55e52df91836 100644 --- a/community/kernel/src/main/java/org/neo4j/kernel/impl/transaction/log/entry/LogEntrySanity.java +++ b/community/kernel/src/main/java/org/neo4j/kernel/impl/transaction/log/entry/LogEntrySanity.java @@ -36,6 +36,7 @@ class LogEntrySanity private LogEntrySanity() { + throw new AssertionError(); } static boolean logEntryMakesSense( LogEntry entry ) @@ -44,13 +45,6 @@ static boolean logEntryMakesSense( LogEntry entry ) { return false; } - - if ( entry instanceof IdentifiableLogEntry ) - { - IdentifiableLogEntry iEntry = (IdentifiableLogEntry) entry; - entry = iEntry.getEntry(); - } - if ( entry instanceof LogEntryStart ) { return startEntryMakesSense( (LogEntryStart) entry ); @@ -62,7 +56,7 @@ else if ( entry instanceof LogEntryCommit ) return true; } - static boolean commitEntryMakesSense( LogEntryCommit entry ) + private static boolean commitEntryMakesSense( LogEntryCommit entry ) { return timeMakesSense( entry.getTimeWritten() ) && transactionIdMakesSense( entry ); } @@ -72,7 +66,7 @@ private static boolean transactionIdMakesSense( LogEntryCommit entry ) return entry.getTxId() > TransactionIdStore.BASE_TX_ID; } - static boolean startEntryMakesSense( LogEntryStart entry ) + private static boolean startEntryMakesSense( LogEntryStart entry ) { return serverIdMakesSense( entry.getLocalId() ) && serverIdMakesSense( entry.getMasterId() ) && @@ -84,7 +78,7 @@ private static boolean serverIdMakesSense( int serverId ) return serverId >= 0 && serverId < UNREASONABLY_HIGH_SERVER_ID; } - static boolean timeMakesSense( long time ) + private static boolean timeMakesSense( long time ) { return abs( currentTimeMillis() - time ) < UNREASONABLY_LONG_TIME; } diff --git a/community/kernel/src/main/java/org/neo4j/kernel/impl/transaction/log/entry/LogEntryStart.java b/community/kernel/src/main/java/org/neo4j/kernel/impl/transaction/log/entry/LogEntryStart.java index a50a74447bd7c..7884d0f2172d6 100644 --- a/community/kernel/src/main/java/org/neo4j/kernel/impl/transaction/log/entry/LogEntryStart.java +++ b/community/kernel/src/main/java/org/neo4j/kernel/impl/transaction/log/entry/LogEntryStart.java @@ -30,8 +30,6 @@ public class LogEntryStart extends AbstractLogEntry { - public static final byte[] EMPTY_ADDITIONAL_ARRAY = new byte[]{}; - private final int masterId; private final int authorId; private final long timeWritten; @@ -132,6 +130,7 @@ public String toString( TimeZone timeZone ) } @Override + @SuppressWarnings( "unchecked" ) public T as() { return (T) this; diff --git a/community/kernel/src/main/java/org/neo4j/kernel/impl/transaction/log/entry/LogEntryVersion.java b/community/kernel/src/main/java/org/neo4j/kernel/impl/transaction/log/entry/LogEntryVersion.java index 095f741624e89..bf6864667246a 100644 --- a/community/kernel/src/main/java/org/neo4j/kernel/impl/transaction/log/entry/LogEntryVersion.java +++ b/community/kernel/src/main/java/org/neo4j/kernel/impl/transaction/log/entry/LogEntryVersion.java @@ -19,7 +19,7 @@ */ package org.neo4j.kernel.impl.transaction.log.entry; -import org.neo4j.kernel.impl.transaction.command.PhysicalLogCommandReaderV2_2_4; +import org.neo4j.kernel.impl.transaction.command.PhysicalLogCommandReaderV3_0_2; import org.neo4j.storageengine.api.StorageCommand; import org.neo4j.storageengine.api.WritableChannel; @@ -40,7 +40,7 @@ * was of the same format. This version actually specified command version, i.e. just versions of one of the * log entry types. This was a bit clunky and forced format specification to be passed in from outside, * based on the log that was read and so updated every time a new log was opened. - * Starting with Neo4j version 2.1 a one-byte log entry version was introduced with every single log entry. + * Starting with Neo4j version 2.1 a one-byte log version field was introduced with every single log entry. * This allowed for more flexible reading and simpler code. Versions started with negative number to be able to * distinguish the new format from the non-versioned format. So observing the log entry type, which was the first * byte in each log entry being negative being negative was a signal for the new format and that the type actually @@ -56,36 +56,19 @@ * the log entry version will be bumped. * The process of making an update to log entry or command format is to: *
    - *
  1. Copy {@link PhysicalLogCommandReaderV2_2_4} or similar and modify the new copy
  2. + *
  3. Copy {@link PhysicalLogCommandReaderV3_0_2} or similar and modify the new copy
  4. *
  5. Copy {@link LogEntryParsersV2_3} or similar and modify the new copy if entry layout has changed
  6. - *
  7. Add an entry in this enum, like {@link #V2_2_4} pointing to the above new classes
  8. + *
  9. Add an entry in this enum, like {@link #V3_0_10} pointing to the above new classes
  10. *
  11. Modify {@link StorageCommand#serialize(WritableChannel)}. * Also {@link LogEntryWriter} (if log entry layout has changed) with required changes
  12. *
  13. Change {@link #CURRENT} to point to the newly created version
  14. *
* Everything apart from that should just work and Neo4j should automatically support the new version as well. - * - * We need to keep going the negative version number route until all supported versions have negative - * version numbers. Then we can have the next version be positive and we should get rid of the: - * read, check < 0, read again thing in {@link VersionAwareLogEntryReader}. */ public enum LogEntryVersion { - // as of 2013-02-09: neo4j 2.0 Labels & Indexing - V2_0( 0, LogEntryParsersV2_0.class ), - // as of 2014-02-06: neo4j 2.1 Dense nodes, split by type/direction into groups - V2_1( -1, LogEntryParsersV2_1.class ), - // as of 2014-05-23: neo4j 2.2 Removal of JTA / unified data source - V2_2( -2, LogEntryParsersV2_2.class ), - // as of 2015-07-23: neo4j 2.2.4 legacy index command header has bigger id space - // -4 is correct, -3 can be found in some 2.3 milestones that's why we play it safe - V2_2_4( -4, LogEntryParsersV2_2_4.class ), V2_3( -5, LogEntryParsersV2_3.class ), V3_0( -6, LogEntryParsersV2_3.class ), - // as of 2016-05-27: neo4j 2.2.10 legacy index IndexDefineCommand maps write size as short instead of byte - // -7 is picked, -5 and -6 can be found in the future (2.3 and 3.0) - // log entry layout hasn't changed since 2_2_4 so just use that one - V2_2_10( -7, LogEntryParsersV2_2_4.class ), // as of 2016-05-30: neo4j 2.3.5 legacy index IndexDefineCommand maps write size as short instead of byte // See comment for V2.2.10 for version number explanation // log entry layout hasn't changed since 2_3 so just use that one @@ -101,7 +84,7 @@ public enum LogEntryVersion public static final LogEntryVersion CURRENT = V3_0_10; private static final LogEntryVersion[] ALL = values(); - private static final LogEntryVersion[] LOOKUP_BY_VERSION = new LogEntryVersion[ALL.length + 1]; // pessimistic size + private static final LogEntryVersion[] LOOKUP_BY_VERSION = new LogEntryVersion[11]; // pessimistic size static { for ( LogEntryVersion version : ALL ) @@ -148,12 +131,11 @@ public LogEntryParser entryParser( byte type ) } /** - * Return the correct {@link LogEntryVersion} for the given {@code version} code read from f.ex a log entry. + * Return the correct {@link LogEntryVersion} for the given {@code version} code read from e.g. a log entry. * Lookup is fast and can be made inside critical paths, no need for externally caching the returned * {@link LogEntryVersion} instance per the input arguments. * * @param version log entry version - * long as we still support those versions. */ public static LogEntryVersion byVersion( byte version ) { diff --git a/community/kernel/src/main/java/org/neo4j/kernel/impl/transaction/log/entry/LogHeaderReader.java b/community/kernel/src/main/java/org/neo4j/kernel/impl/transaction/log/entry/LogHeaderReader.java index 0962b761bf992..1bbde1569dd40 100644 --- a/community/kernel/src/main/java/org/neo4j/kernel/impl/transaction/log/entry/LogHeaderReader.java +++ b/community/kernel/src/main/java/org/neo4j/kernel/impl/transaction/log/entry/LogHeaderReader.java @@ -91,12 +91,12 @@ public static LogHeader readLogHeader( ByteBuffer buffer, ReadableByteChannel ch return new LogHeader( logFormatVersion, logVersion, previousCommittedTx ); } - public static long decodeLogVersion( long encLogVersion ) + static long decodeLogVersion( long encLogVersion ) { return encLogVersion & 0x00FFFFFFFFFFFFFFL; } - public static byte decodeLogFormatVersion( long encLogVersion ) + static byte decodeLogFormatVersion( long encLogVersion ) { return (byte) ((encLogVersion >> 56) & 0xFF); } diff --git a/community/kernel/src/main/java/org/neo4j/kernel/impl/transaction/log/entry/OnePhaseCommit.java b/community/kernel/src/main/java/org/neo4j/kernel/impl/transaction/log/entry/OnePhaseCommit.java index 5a6c08d6b422f..f480dc24e8109 100644 --- a/community/kernel/src/main/java/org/neo4j/kernel/impl/transaction/log/entry/OnePhaseCommit.java +++ b/community/kernel/src/main/java/org/neo4j/kernel/impl/transaction/log/entry/OnePhaseCommit.java @@ -35,6 +35,7 @@ public OnePhaseCommit( LogEntryVersion version, long txId, long timeWritten ) } @Override + @SuppressWarnings( "unchecked" ) public T as() { return (T) this; diff --git a/community/kernel/src/main/java/org/neo4j/kernel/impl/transaction/log/entry/VersionAwareLogEntryReader.java b/community/kernel/src/main/java/org/neo4j/kernel/impl/transaction/log/entry/VersionAwareLogEntryReader.java index 127708ce7b32c..55b0cc0ec4fae 100644 --- a/community/kernel/src/main/java/org/neo4j/kernel/impl/transaction/log/entry/VersionAwareLogEntryReader.java +++ b/community/kernel/src/main/java/org/neo4j/kernel/impl/transaction/log/entry/VersionAwareLogEntryReader.java @@ -20,6 +20,7 @@ package org.neo4j.kernel.impl.transaction.log.entry; import java.io.IOException; + import org.neo4j.kernel.impl.storageengine.impl.recordstorage.RecordStorageCommandReaderFactory; import org.neo4j.kernel.impl.transaction.log.LogPosition; import org.neo4j.kernel.impl.transaction.log.LogPositionMarker; @@ -36,9 +37,7 @@ /** * Version aware implementation of LogEntryReader * Starting with Neo4j version 2.1, log entries are prefixed with a version. This allows for Neo4j instances of - * different versions to exchange transaction data, either directly or via logical logs. This implementation of - * LogEntryReader makes use of the version information to deserialize command entries that hold commands created - * with previous versions of Neo4j. + * different versions to exchange transaction data, either directly or via logical logs. * * Read all about it at {@link LogEntryVersion}. */ @@ -70,24 +69,12 @@ public LogEntry readLogEntry( SOURCE channel ) throws IOException { channel.getCurrentPosition( positionMarker ); - byte typeCode; - byte versionCode; - try + byte versionCode = channel.get(); + if ( versionCode == 0 ) { - typeCode = channel.get(); - versionCode = 0; - if ( typeCode < 0 ) - { - // if the read type is negative than it is actually the log entry version - // so we need to read an extra byte which will contain the type - versionCode = typeCode; - typeCode = channel.get(); - } - } - catch ( ReadPastEndException e ) - { // Make these exceptions slip by straight out to the outer handler - throw e; + return null; } + byte typeCode = channel.get(); LogEntryVersion version = null; LogEntryParser entryReader; diff --git a/community/kernel/src/test/java/org/neo4j/kernel/impl/storemigration/legacylogs/LegacyLogEntryReaderTest.java b/community/kernel/src/test/java/org/neo4j/kernel/impl/storemigration/legacylogs/LegacyLogEntryReaderTest.java deleted file mode 100644 index 0cf1f19480f8a..0000000000000 --- a/community/kernel/src/test/java/org/neo4j/kernel/impl/storemigration/legacylogs/LegacyLogEntryReaderTest.java +++ /dev/null @@ -1,138 +0,0 @@ -/* - * Copyright (c) 2002-2017 "Neo Technology," - * Network Engine for Objects in Lund AB [http://neotechnology.com] - * - * This file is part of Neo4j. - * - * Neo4j is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ -package org.neo4j.kernel.impl.storemigration.legacylogs; - -import org.junit.Before; -import org.junit.Rule; -import org.junit.Test; - -import java.io.File; -import java.io.IOException; -import java.util.function.Function; - -import org.neo4j.cursor.IOCursor; -import org.neo4j.helpers.collection.Pair; -import org.neo4j.io.fs.FileSystemAbstraction; -import org.neo4j.kernel.impl.store.record.NodeRecord; -import org.neo4j.kernel.impl.transaction.command.Command; -import org.neo4j.kernel.impl.transaction.log.ReadableLogChannel; -import org.neo4j.kernel.impl.transaction.log.entry.IdentifiableLogEntry; -import org.neo4j.kernel.impl.transaction.log.entry.LogEntry; -import org.neo4j.kernel.impl.transaction.log.entry.LogEntryCommand; -import org.neo4j.kernel.impl.transaction.log.entry.LogEntryReader; -import org.neo4j.kernel.impl.transaction.log.entry.LogEntryStart; -import org.neo4j.kernel.impl.transaction.log.entry.LogHeader; -import org.neo4j.kernel.impl.transaction.log.entry.OnePhaseCommit; -import org.neo4j.test.rule.fs.EphemeralFileSystemRule; - -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertFalse; -import static org.junit.Assert.assertNull; -import static org.junit.Assert.assertTrue; -import static org.mockito.Matchers.any; -import static org.mockito.Mockito.mock; -import static org.mockito.Mockito.when; -import static org.neo4j.kernel.impl.storemigration.legacylogs.LegacyLogFilenames.getLegacyLogFilename; -import static org.neo4j.kernel.impl.transaction.log.LogPosition.UNSPECIFIED; -import static org.neo4j.kernel.impl.transaction.log.TransactionIdStore.BASE_TX_ID; -import static org.neo4j.kernel.impl.transaction.log.entry.LogEntryStart.EMPTY_ADDITIONAL_ARRAY; -import static org.neo4j.kernel.impl.transaction.log.entry.LogHeaderWriter.writeLogHeader; -import static org.neo4j.kernel.impl.transaction.log.entry.LogVersions.CURRENT_LOG_VERSION; - -public class LegacyLogEntryReaderTest -{ - @Rule - public final EphemeralFileSystemRule fileSystemRule = new EphemeralFileSystemRule(); - private final FileSystemAbstraction fs = fileSystemRule.get(); - private final File input = new File( getLegacyLogFilename( 3 ) ); - - @Before - public void setup() throws IOException - { - writeLogHeader( fs, input, 3L, -1 ); - } - - @Test - public void shouldReadTheLogHeaderAndSetCurrentVersionAndABaseTxIdIfNegative() throws IOException - { - // given - final LegacyLogEntryReader reader = new LegacyLogEntryReader( fs ); - - // when - final Pair> pair = reader.openReadableChannel( input ); - - // then - pair.other().close(); // not null cursor - assertEquals( new LogHeader( CURRENT_LOG_VERSION, 3L, BASE_TX_ID ), pair.first() ); - } - - @Test - public void shouldReturnNoEntriesWhenTheChannelContainsNothing() throws IOException - { - // given - final LogEntryReader logEntryReader = mock( LogEntryReader.class ); - when( logEntryReader.readLogEntry( any( ReadableLogChannel.class ) ) ).thenReturn( null ); - final LegacyLogEntryReader reader = new LegacyLogEntryReader( fs, - from -> logEntryReader ); - - // when - final IOCursor cursor = reader.openReadableChannel( input ).other(); - - // then - assertFalse( cursor.next() ); - assertNull( cursor.get() ); - - cursor.close(); - } - - @Test - public void shouldReadTheEntries() throws IOException - { - // given - final LogEntry start = new LogEntryStart( 0, 1, 2, 3, EMPTY_ADDITIONAL_ARRAY, UNSPECIFIED ); - NodeRecord record = new NodeRecord( 42 ); - final LogEntry command = new LogEntryCommand( new Command.NodeCommand( record, record ) ); - final LogEntry commit = new OnePhaseCommit( 42, 43 ); - - final LogEntryReader logEntryReader = mock( LogEntryReader.class ); - when( logEntryReader.readLogEntry( any( ReadableLogChannel.class ) ) ).thenReturn( - new IdentifiableLogEntry( start, 1 ), - new IdentifiableLogEntry( command, 1 ), - new IdentifiableLogEntry( commit, 1 ), - null - ); - - final LegacyLogEntryReader reader = new LegacyLogEntryReader( fs, from -> logEntryReader ); - - // when - final IOCursor cursor = reader.openReadableChannel( input ).other(); - - // then - assertTrue( cursor.next() ); - assertEquals( start, cursor.get() ); - assertTrue( cursor.next() ); - assertEquals( command, cursor.get() ); - assertTrue( cursor.next() ); - assertEquals( commit, cursor.get() ); - assertFalse( cursor.next() ); - - cursor.close(); - } -} diff --git a/community/kernel/src/test/java/org/neo4j/kernel/impl/storemigration/legacylogs/LegacyLogEntryWriterTest.java b/community/kernel/src/test/java/org/neo4j/kernel/impl/storemigration/legacylogs/LegacyLogEntryWriterTest.java deleted file mode 100644 index dd10eb5803a8c..0000000000000 --- a/community/kernel/src/test/java/org/neo4j/kernel/impl/storemigration/legacylogs/LegacyLogEntryWriterTest.java +++ /dev/null @@ -1,149 +0,0 @@ -/* - * Copyright (c) 2002-2017 "Neo Technology," - * Network Engine for Objects in Lund AB [http://neotechnology.com] - * - * This file is part of Neo4j. - * - * Neo4j is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ -package org.neo4j.kernel.impl.storemigration.legacylogs; - -import org.junit.Rule; -import org.junit.Test; - -import java.io.File; -import java.io.IOException; -import java.util.Arrays; -import java.util.function.Function; - -import org.neo4j.cursor.IOCursor; -import org.neo4j.io.fs.FileSystemAbstraction; -import org.neo4j.kernel.impl.store.record.NodeRecord; -import org.neo4j.kernel.impl.store.record.RelationshipRecord; -import org.neo4j.kernel.impl.transaction.TransactionRepresentation; -import org.neo4j.kernel.impl.transaction.command.Command; -import org.neo4j.kernel.impl.transaction.log.ArrayIOCursor; -import org.neo4j.kernel.impl.transaction.log.FlushableChannel; -import org.neo4j.kernel.impl.transaction.log.LogVersionedStoreChannel; -import org.neo4j.kernel.impl.transaction.log.PhysicalTransactionRepresentation; -import org.neo4j.kernel.impl.transaction.log.entry.LogEntry; -import org.neo4j.kernel.impl.transaction.log.entry.LogEntryCommand; -import org.neo4j.kernel.impl.transaction.log.entry.LogEntryCommit; -import org.neo4j.kernel.impl.transaction.log.entry.LogEntryStart; -import org.neo4j.kernel.impl.transaction.log.entry.LogEntryWriter; -import org.neo4j.kernel.impl.transaction.log.entry.LogHeader; -import org.neo4j.kernel.impl.transaction.log.entry.OnePhaseCommit; -import org.neo4j.test.rule.fs.EphemeralFileSystemRule; - -import static org.junit.Assert.assertEquals; -import static org.mockito.Matchers.eq; -import static org.mockito.Mockito.mock; -import static org.mockito.Mockito.times; -import static org.mockito.Mockito.verify; -import static org.neo4j.kernel.impl.storemigration.legacylogs.LegacyLogFilenames.getLegacyLogFilename; -import static org.neo4j.kernel.impl.transaction.log.LogPosition.UNSPECIFIED; -import static org.neo4j.kernel.impl.transaction.log.entry.LogEntryStart.EMPTY_ADDITIONAL_ARRAY; -import static org.neo4j.kernel.impl.transaction.log.entry.LogHeaderReader.readLogHeader; -import static org.neo4j.kernel.impl.transaction.log.entry.LogVersions.CURRENT_LOG_VERSION; - -public class LegacyLogEntryWriterTest -{ - @Rule - public final EphemeralFileSystemRule fileSystemRule = new EphemeralFileSystemRule(); - - private final FileSystemAbstraction fs = fileSystemRule.get(); - private final NodeRecord nodeRecord = new NodeRecord( 42L ); - private final RelationshipRecord relRecord = new RelationshipRecord( 42L ); - - @Test - public void shouldWriteTheHeaderInTheFile() throws IOException - { - // given - final LegacyLogEntryWriter writer = new LegacyLogEntryWriter( fs ); - final File output = new File( getLegacyLogFilename( 3 ) ); - final LogHeader header = new LogHeader( CURRENT_LOG_VERSION, 1, 42L ); - - // when - try ( LogVersionedStoreChannel channel = writer.openWritableChannel( output ) ) - { - writer.writeLogHeader( channel, header ); - } - // then - assertEquals( header, readLogHeader( fs, output ) ); - } - - @Test - public void shouldWriteAllTheEntryInACommitToTheFile() throws IOException - { - // given - final LogVersionedStoreChannel channel = mock( LogVersionedStoreChannel.class ); - final LogEntryWriter logEntryWriter = mock( LogEntryWriter.class ); - final LegacyLogEntryWriter writer = new LegacyLogEntryWriter( fs, liftToFactory( logEntryWriter ) ); - final LogEntryStart start = new LogEntryStart( 0, 1, 2L, 3L, EMPTY_ADDITIONAL_ARRAY, UNSPECIFIED ); - final LogEntryCommand command = new LogEntryCommand( new Command.NodeCommand( nodeRecord, nodeRecord ) ); - final LogEntryCommit commit = new OnePhaseCommit( 42L, 43L ); - - // when - final IOCursor cursor = mockCursor( start, command, commit ); - writer.writeAllLogEntries( channel, cursor ); - - // then - verify( logEntryWriter, times( 1 ) ).writeStartEntry( 0, 1, 2L, 3L, EMPTY_ADDITIONAL_ARRAY ); - final TransactionRepresentation expected = - new PhysicalTransactionRepresentation( Arrays.asList( command.getXaCommand() ) ); - verify( logEntryWriter, times( 1 ) ).serialize( eq( expected ) ); - verify( logEntryWriter, times( 1 ) ).writeCommitEntry( 42L, 43L ); - } - - @Test - public void shouldWriteAllTheEntryInSeveralCommitsToTheFile() throws IOException - { - // given - final LogVersionedStoreChannel channel = mock( LogVersionedStoreChannel.class ); - final LogEntryWriter logEntryWriter = mock( LogEntryWriter.class ); - final LegacyLogEntryWriter writer = new LegacyLogEntryWriter( fs, liftToFactory( logEntryWriter ) ); - final LogEntryStart start1 = new LogEntryStart( 0, 1, 2L, 3L, EMPTY_ADDITIONAL_ARRAY, UNSPECIFIED ); - final LogEntryCommand command1 = new LogEntryCommand( new Command.NodeCommand( nodeRecord, nodeRecord ) ); - final LogEntryCommit commit1 = new OnePhaseCommit( 42L, 43L ); - final LogEntryStart start2 = new LogEntryStart( 9, 8, 7L, 6L, EMPTY_ADDITIONAL_ARRAY, UNSPECIFIED ); - final LogEntryCommand command2 = new LogEntryCommand( new Command.RelationshipCommand( relRecord, relRecord ) ); - final LogEntryCommit commit2 = new OnePhaseCommit( 84L, 85L ); - - // when - IOCursor cursor = mockCursor( start1, command1, commit1, start2, command2, commit2 ); - writer.writeAllLogEntries( channel, cursor ); - - // then - verify( logEntryWriter, times( 1 ) ).writeStartEntry( 0, 1, 2L, 3L, EMPTY_ADDITIONAL_ARRAY ); - final TransactionRepresentation expected1 = - new PhysicalTransactionRepresentation( Arrays.asList( command1.getXaCommand() ) ); - verify( logEntryWriter, times( 1 ) ).serialize( eq( expected1 ) ); - verify( logEntryWriter, times( 1 ) ).writeCommitEntry( 42L, 43L ); - verify( logEntryWriter, times( 1 ) ).writeStartEntry( 9, 8, 7L, 6L, EMPTY_ADDITIONAL_ARRAY ); - final TransactionRepresentation expected2 = - new PhysicalTransactionRepresentation( Arrays.asList( command2.getXaCommand() ) ); - verify( logEntryWriter, times( 1 ) ).serialize( eq( expected2 ) ); - verify( logEntryWriter, times( 1 ) ).writeCommitEntry( 84L, 85L ); - } - - private Function liftToFactory( final LogEntryWriter logEntryWriter ) - { - return ignored -> logEntryWriter; - } - - private IOCursor mockCursor( final LogEntry... entries ) - { - return new ArrayIOCursor<>( entries ); - } -} diff --git a/community/kernel/src/test/java/org/neo4j/kernel/impl/storemigration/legacylogs/LegacyLogsTest.java b/community/kernel/src/test/java/org/neo4j/kernel/impl/storemigration/legacylogs/LegacyLogsTest.java deleted file mode 100644 index 36329b2dc4fd8..0000000000000 --- a/community/kernel/src/test/java/org/neo4j/kernel/impl/storemigration/legacylogs/LegacyLogsTest.java +++ /dev/null @@ -1,289 +0,0 @@ -/* - * Copyright (c) 2002-2017 "Neo Technology," - * Network Engine for Objects in Lund AB [http://neotechnology.com] - * - * This file is part of Neo4j. - * - * Neo4j is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ -package org.neo4j.kernel.impl.storemigration.legacylogs; - -import org.junit.Test; - -import java.io.File; -import java.io.FilenameFilter; -import java.io.IOException; -import java.nio.ByteBuffer; -import java.util.Arrays; -import java.util.HashSet; -import java.util.List; -import java.util.Set; - -import org.neo4j.cursor.IOCursor; -import org.neo4j.graphdb.mockfs.EphemeralFileSystemAbstraction; -import org.neo4j.helpers.collection.Pair; -import org.neo4j.io.fs.FileSystemAbstraction; -import org.neo4j.io.fs.StoreChannel; -import org.neo4j.kernel.impl.store.TransactionId; -import org.neo4j.kernel.impl.store.record.NodeRecord; -import org.neo4j.kernel.impl.store.record.Record; -import org.neo4j.kernel.impl.storemigration.FileOperation; -import org.neo4j.kernel.impl.transaction.command.Command; -import org.neo4j.kernel.impl.transaction.log.ArrayIOCursor; -import org.neo4j.kernel.impl.transaction.log.LogPosition; -import org.neo4j.kernel.impl.transaction.log.LogVersionedStoreChannel; -import org.neo4j.kernel.impl.transaction.log.MissingLogDataException; -import org.neo4j.kernel.impl.transaction.log.entry.LogEntry; -import org.neo4j.kernel.impl.transaction.log.entry.LogEntryCommand; -import org.neo4j.kernel.impl.transaction.log.entry.LogEntryStart; -import org.neo4j.kernel.impl.transaction.log.entry.LogHeader; -import org.neo4j.kernel.impl.transaction.log.entry.OnePhaseCommit; - -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertFalse; -import static org.mockito.Matchers.any; -import static org.mockito.Mockito.mock; -import static org.mockito.Mockito.times; -import static org.mockito.Mockito.verify; -import static org.mockito.Mockito.when; -import static org.neo4j.kernel.impl.storemigration.legacylogs.LegacyLogFilenames.getLegacyLogFilename; -import static org.neo4j.kernel.impl.storemigration.legacylogs.LegacyLogFilenames.versionedLegacyLogFilesFilter; -import static org.neo4j.kernel.impl.transaction.log.PhysicalLogFile.DEFAULT_NAME; -import static org.neo4j.kernel.impl.transaction.log.PhysicalLogFile.DEFAULT_VERSION_SUFFIX; -import static org.neo4j.kernel.impl.transaction.log.entry.LogVersions.CURRENT_LOG_VERSION; - -public class LegacyLogsTest -{ - private static final long NO_NEXT_REL = Record.NO_NEXT_RELATIONSHIP.intValue(); - private static final int NO_LABELS = Record.NO_LABELS_FIELD.intValue(); - - private final FileSystemAbstraction fs = mock( FileSystemAbstraction.class ); - private final LegacyLogEntryReader reader = mock( LegacyLogEntryReader.class ); - private final LegacyLogEntryWriter writer = mock( LegacyLogEntryWriter.class ); - private final File storeDir = getRootFile( "/store" ); - private final File migrationDir = getRootFile( "/migration" ); - - private static File getRootFile( String pathname ) - { - try - { - return new File( pathname ).getCanonicalFile(); - } - catch ( IOException e ) - { - throw new AssertionError( e ); - } - } - - @Test - public void shouldRewriteLogFiles() throws IOException - { - // given - final IOCursor cursor = mock( IOCursor.class ); - final LogVersionedStoreChannel writeChannel = mock( LogVersionedStoreChannel.class ); - final LogHeader header = new LogHeader( CURRENT_LOG_VERSION, 1, 42 ); - when( fs.listFiles( storeDir, versionedLegacyLogFilesFilter ) ).thenReturn( new File[]{ - new File( getLegacyLogFilename( 1 ) ) - } ); - when( reader.openReadableChannel( new File( getLegacyLogFilename( 1 ) ) ) ).thenReturn( - Pair.of( header, cursor ) - ); - when( writer.openWritableChannel( new File( migrationDir, getLegacyLogFilename( 1 ) ) ) ). - thenReturn( writeChannel ); - - // when - new LegacyLogs( fs, reader, writer ).migrateLogs( storeDir, migrationDir ); - - // then - verify( writer, times( 1 ) ).writeLogHeader( writeChannel, header ); - verify( writer, times( 1 ) ).writeAllLogEntries( writeChannel, cursor ); - } - - @Test - public void shouldMoveFiles() throws Exception - { - // given - try ( EphemeralFileSystemAbstraction fs = new EphemeralFileSystemAbstraction() ) - { - fs.mkdirs( storeDir ); - fs.mkdirs( migrationDir ); - - final Set logsInStoreDir = new HashSet<>( Arrays.asList( new File( storeDir, getLegacyLogFilename( 1 ) ), - new File( storeDir, getLegacyLogFilename( 2 ) ) ) ); - - final List logsInMigrationDir = Arrays.asList( new File( migrationDir, getLegacyLogFilename( 1 ) ), - new File( migrationDir, getLegacyLogFilename( 2 ) ) ); - - for ( File file : logsInMigrationDir ) - { - try ( StoreChannel channel = fs.create( file ) ) - { - ByteBuffer buffer = ByteBuffer.allocate( 8 ); - buffer.putLong( 42 ); - buffer.flip(); - channel.write( buffer ); - } - } - - // should override older files - for ( File file : logsInStoreDir ) - { - try ( StoreChannel channel = fs.create( file ) ) - { - ByteBuffer buffer = ByteBuffer.allocate( 8 ); - buffer.putLong( 13 ); - buffer.flip(); - channel.write( buffer ); - } - } - - // when - new LegacyLogs( fs, reader, writer ).operate( FileOperation.MOVE, migrationDir, storeDir ); - - // then - assertEquals( logsInStoreDir, new HashSet<>( Arrays.asList( fs.listFiles( storeDir ) ) ) ); - for ( File file : logsInStoreDir ) - { - try ( StoreChannel channel = fs.open( file, "r" ) ) - { - ByteBuffer buffer = ByteBuffer.allocate( 8 ); - channel.read( buffer ); - buffer.flip(); - assertEquals( 42, buffer.getLong() ); - } - } - } - } - - @Test - public void shouldRenameFiles() throws Exception - { - // given - try ( EphemeralFileSystemAbstraction fs = new EphemeralFileSystemAbstraction() ) - { - fs.mkdirs( storeDir ); - final File unrelated = new File( storeDir, "unrelated" ); - final List files = - Arrays.asList( new File( storeDir, "active_tx_log" ), new File( storeDir, "tm_tx_log.v0" ), - new File( storeDir, "tm_tx_log.v1" ), new File( storeDir, "nioneo_logical.log.1" ), - new File( storeDir, "nioneo_logical.log.2" ), new File( storeDir, getLegacyLogFilename( 1 ) ), - new File( storeDir, getLegacyLogFilename( 2 ) ), unrelated ); - - for ( File file : files ) - { - fs.create( file ).close(); - } - - // when - new LegacyLogs( fs, reader, writer ).renameLogFiles( storeDir ); - - // then - final Set expected = new HashSet<>( - Arrays.asList( unrelated, new File( storeDir, getLogFilenameForVersion( 1 ) ), - new File( storeDir, getLogFilenameForVersion( 2 ) ) ) ); - assertEquals( expected, new HashSet<>( Arrays.asList( fs.listFiles( storeDir ) ) ) ); - } - } - - @Test - @SuppressWarnings( "unchecked" ) - public void transactionInformationRetrievedFromCommitEntries() throws IOException - { - FileSystemAbstraction fs = mock( FileSystemAbstraction.class ); - File logFile = new File( LegacyLogFilenames.getLegacyLogFilename( 1 ) ); - when( fs.listFiles( any( File.class ), any( FilenameFilter.class ) ) ) - .thenReturn( new File[]{logFile} ); - - LegacyLogEntryReader reader = mock( LegacyLogEntryReader.class ); - LogEntry[] entries = new LogEntry[]{ - start( 1 ), createNode( 1 ), createNode( 2 ), commit( 1 ), - start( 2 ), createNode( 3 ), createNode( 4 ), commit( 2 ), - start( 3 ), createNode( 5 ), commit( 3 ) - }; - when( reader.openReadableChannel( any( File.class ) ) ) - .thenReturn( readableChannel( entries ), readableChannel( entries ), readableChannel( entries ) ); - - LegacyLogEntryWriter writer = new LegacyLogEntryWriter( fs ); - LegacyLogs legacyLogs = new LegacyLogs( fs, reader, writer ); - - assertEquals( newTransactionId( 1 ), getTransactionInformation( legacyLogs, 1 ) ); - assertEquals( newTransactionId( 2 ), getTransactionInformation( legacyLogs, 2 ) ); - assertEquals( newTransactionId( 3 ), getTransactionInformation( legacyLogs, 3 ) ); - } - - @Test( expected = IOException.class ) - @SuppressWarnings( "unchecked" ) - public void ioExceptionsPropagatedWhenFailToReadLegacyLog() throws IOException - { - File logFile = new File( LegacyLogFilenames.getLegacyLogFilename( 1 ) ); - when( fs.listFiles( any( File.class ), any( FilenameFilter.class ) ) ) - .thenReturn( new File[]{logFile} ); - - when( reader.openReadableChannel( any( File.class ) ) ).thenThrow( IOException.class ); - - LegacyLogs legacyLogs = new LegacyLogs( fs, reader, writer ); - getTransactionInformation( legacyLogs, 1 ); - } - - @Test - public void noTransactionalInformationWhenLogsNotPresent() throws IOException - { - when( fs.listFiles( any( File.class ), any( FilenameFilter.class ) ) ) - .thenReturn( new File[]{} ); - - LegacyLogs legacyLogs = new LegacyLogs( fs, reader, writer ); - assertFalse( "There are not logs. Nothing to return", - legacyLogs.getTransactionInformation( storeDir, 1 ).isPresent() ); - } - - private TransactionId getTransactionInformation( LegacyLogs legacyLogs, int transactionId ) throws IOException - { - return legacyLogs.getTransactionInformation( storeDir, transactionId ).orElseThrow( MissingLogDataException::new); - } - - private String getLogFilenameForVersion( int version ) - { - return DEFAULT_NAME + DEFAULT_VERSION_SUFFIX + version; - } - - private static TransactionId newTransactionId( int id ) - { - return new TransactionId( id, LogEntryStart.checksum( new byte[]{(byte) id}, id, id ), id ); - } - - private static LogEntry start( int id ) - { - return new LogEntryStart( id, id, 1, id - 1, new byte[]{(byte) id}, new LogPosition( 1, 1 ) ); - } - - private static LogEntry createNode( int id ) - { - NodeRecord before = new NodeRecord( id ).initialize( false, NO_NEXT_REL, false, NO_NEXT_REL, NO_LABELS ); - NodeRecord after = new NodeRecord( id ).initialize( true, NO_NEXT_REL, false, NO_NEXT_REL, NO_LABELS ); - Command.NodeCommand command = new Command.NodeCommand( before, after ); - return new LogEntryCommand( command ); - } - - private static LogEntry commit( int id ) - { - return new OnePhaseCommit( id, id ); - } - - private Pair> readableChannel( LogEntry[] entries ) - { - IOCursor cursor = new ArrayIOCursor<>( entries ); - LogHeader logHeader = new LogHeader( (byte) 1, 1, 1 ); - return Pair.of( logHeader, cursor ); - } -} diff --git a/community/kernel/src/test/java/org/neo4j/kernel/impl/storemigration/legacylogs/LogEntrySortingCursorTest.java b/community/kernel/src/test/java/org/neo4j/kernel/impl/storemigration/legacylogs/LogEntrySortingCursorTest.java deleted file mode 100644 index 594023435262c..0000000000000 --- a/community/kernel/src/test/java/org/neo4j/kernel/impl/storemigration/legacylogs/LogEntrySortingCursorTest.java +++ /dev/null @@ -1,197 +0,0 @@ -/* - * Copyright (c) 2002-2017 "Neo Technology," - * Network Engine for Objects in Lund AB [http://neotechnology.com] - * - * This file is part of Neo4j. - * - * Neo4j is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ -package org.neo4j.kernel.impl.storemigration.legacylogs; - -import org.junit.Test; - -import java.io.IOException; -import java.util.Arrays; -import java.util.List; -import java.util.Random; - -import org.neo4j.kernel.impl.store.record.NodeRecord; -import org.neo4j.kernel.impl.transaction.command.Command; -import org.neo4j.kernel.impl.transaction.log.ReadableLogChannel; -import org.neo4j.kernel.impl.transaction.log.entry.IdentifiableLogEntry; -import org.neo4j.kernel.impl.transaction.log.entry.LogEntry; -import org.neo4j.kernel.impl.transaction.log.entry.LogEntryCommand; -import org.neo4j.kernel.impl.transaction.log.entry.LogEntryReader; -import org.neo4j.kernel.impl.transaction.log.entry.LogEntryStart; -import org.neo4j.kernel.impl.transaction.log.entry.OnePhaseCommit; - -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertFalse; -import static org.junit.Assert.assertTrue; -import static org.mockito.Mockito.mock; -import static org.mockito.Mockito.when; -import static org.neo4j.kernel.impl.transaction.log.LogPosition.UNSPECIFIED; -import static org.neo4j.kernel.impl.transaction.log.entry.LogEntryStart.EMPTY_ADDITIONAL_ARRAY; - -public class LogEntrySortingCursorTest -{ - private static final Random random = new Random( 42L ); - private final ReadableLogChannel channel = mock( ReadableLogChannel.class ); - @SuppressWarnings( "unchecked" ) - private final LogEntryReader reader = mock( LogEntryReader.class ); - - @Test - public void shouldDoNothingIfTheListIsOrdered() throws IOException - { - // given - final LogEntry start1 = start( 1 ); - final LogEntry command1 = command(); - final LogEntry commit1 = commit( 2 ); - - final LogEntry start2 = start( 2 ); - final LogEntry command2 = command(); - final LogEntry commit2 = commit( 3 ); - - when( reader.readLogEntry( channel ) ).thenReturn( - id( start1, 1 ), id( command1, 1 ), id( commit1, 1 ), - id( start2, 2 ), id( command2, 2 ), id( commit2, 2 ), - null - ); - - // when - final LogEntrySortingCursor cursor = new LogEntrySortingCursor( reader, channel ); - - // then - final List expected = Arrays.asList( start1, command1, commit1, start2, command2, commit2 ); - assertCursorContains( expected, cursor ); - } - - @Test - public void shouldReorderBasedOnTheTxId() throws IOException - { - // given - final LogEntry start1 = start( 3 ); - final LogEntry command1 = command(); - final LogEntry commit1 = commit( 5 ); - - final LogEntry start2 = start( 3 ); - final LogEntry command2 = command(); - final LogEntry commit2 = commit( 4 ); - - when( reader.readLogEntry( channel ) ).thenReturn( - id( start1, 1 ), id( command1, 1 ), - id( start2, 2 ), id( command2, 2 ), id( commit2, 2 ), - id( commit1, 1 ), - null - ); - - // when - final LogEntrySortingCursor cursor = new LogEntrySortingCursor( reader, channel ); - - // then - final List expected = Arrays.asList( start2, command2, commit2, start1, command1, commit1 ); - assertCursorContains( expected, cursor ); - } - - @Test - public void shouldReorderWhenEntriesAreMixedUp() throws IOException - { - // given - final LogEntry start1 = start( 3 ); - final LogEntry command1 = command(); - final LogEntry commit1 = commit( 5 ); - - final LogEntry start2 = start( 3 ); - final LogEntry command2 = command(); - final LogEntry commit2 = commit( 4 ); - - when( reader.readLogEntry( channel ) ).thenReturn( - id( start2, 2 ), - id( start1, 1 ), - id( command1, 1 ), - id( command2, 2 ), - id( commit2, 2 ), - id( commit1, 1 ), - null - ); - - // when - final LogEntrySortingCursor cursor = new LogEntrySortingCursor( reader, channel ); - - // then - final List expected = Arrays.asList( start2, command2, commit2, start1, command1, commit1 ); - assertCursorContains( expected, cursor ); - } - - @Test - public void shouldBeFineIfThereAreEntriesWithoutACommit() throws IOException - { - // given - final LogEntry start1 = start( 3 ); - final LogEntry command1 = command(); - - final LogEntry start2 = start( 3 ); - final LogEntry command2 = command(); - final LogEntry commit2 = commit( 4 ); - - when( reader.readLogEntry( channel ) ).thenReturn( - id( start2, 2 ), - id( start1, 1 ), - id( command1, 1 ), - id( command2, 2 ), - id( commit2, 2 ), - null - ); - - // when - final LogEntrySortingCursor cursor = new LogEntrySortingCursor( reader, channel ); - - // then - final List expected = Arrays.asList( start2, command2, commit2 ); - assertCursorContains( expected, cursor ); - } - - private void assertCursorContains( Iterable entries, LogEntrySortingCursor cursor ) throws IOException - { - for ( LogEntry entry : entries ) - { - assertTrue( cursor.next() ); - assertEquals( entry, cursor.get() ); - } - assertFalse( cursor.next() ); - } - - private LogEntry start( long lastTxId ) - { - return new LogEntryStart( random.nextInt(), random.nextInt(), random.nextLong(), - lastTxId, EMPTY_ADDITIONAL_ARRAY, UNSPECIFIED ); - } - - private LogEntry command() - { - NodeRecord before = new NodeRecord( random.nextInt() ); - NodeRecord after = new NodeRecord( random.nextInt() ); - return new LogEntryCommand( new Command.NodeCommand( before, after ) ); - } - - private LogEntry commit( long txId ) - { - return new OnePhaseCommit( txId, random.nextInt() ); - } - - private IdentifiableLogEntry id( LogEntry entry, int id ) - { - return new IdentifiableLogEntry( entry, id ); - } -} diff --git a/community/kernel/src/test/java/org/neo4j/kernel/impl/storemigration/participant/StoreMigratorTest.java b/community/kernel/src/test/java/org/neo4j/kernel/impl/storemigration/participant/StoreMigratorTest.java index 9c69a25de9180..e1e2fcb9208c6 100644 --- a/community/kernel/src/test/java/org/neo4j/kernel/impl/storemigration/participant/StoreMigratorTest.java +++ b/community/kernel/src/test/java/org/neo4j/kernel/impl/storemigration/participant/StoreMigratorTest.java @@ -26,7 +26,6 @@ import java.io.File; import java.io.IOException; -import java.util.Optional; import org.neo4j.io.pagecache.PageCache; import org.neo4j.kernel.api.index.SchemaIndexProvider; @@ -38,7 +37,6 @@ import org.neo4j.kernel.impl.store.TransactionId; import org.neo4j.kernel.impl.store.format.standard.StandardV3_0; import org.neo4j.kernel.impl.store.format.standard.StandardV3_2; -import org.neo4j.kernel.impl.storemigration.legacylogs.LegacyLogs; import org.neo4j.kernel.impl.storemigration.monitoring.MigrationProgressMonitor; import org.neo4j.kernel.impl.transaction.log.LogPosition; import org.neo4j.kernel.impl.transaction.log.TransactionIdStore; @@ -51,7 +49,6 @@ import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertFalse; import static org.mockito.Mockito.mock; -import static org.mockito.Mockito.when; import static org.neo4j.kernel.impl.store.MetaDataStore.DEFAULT_NAME; import static org.neo4j.kernel.impl.store.MetaDataStore.Position.LAST_TRANSACTION_CHECKSUM; import static org.neo4j.kernel.impl.store.MetaDataStore.Position.LAST_TRANSACTION_COMMIT_TIMESTAMP; @@ -114,37 +111,6 @@ public void shouldExtractTransactionInformationFromMetaDataStore() throws Except assertEquals( expected, actual ); } - @Test - public void shouldExtractTransactionInformationFromLegacyLogsWhenCantFindInStore() throws Exception - { - // given - // ... variables - long txId = 42; - long checksum = 123456789123456789L; - long timestamp = 919191919191919191L; - TransactionId expected = new TransactionId( txId, checksum, timestamp ); - - // ... and files - File storeDir = directory.graphDbDir(); - File neoStore = new File( storeDir, DEFAULT_NAME ); - neoStore.createNewFile(); - - // ... and mocks - Config config = mock( Config.class ); - LogService logService = mock( LogService.class ); - LegacyLogs legacyLogs = mock( LegacyLogs.class ); - when( legacyLogs.getTransactionInformation( storeDir, txId ) ).thenReturn( Optional.of( expected ) ); - - // when - // ... neoStore is empty and with migrator - StoreMigrator migrator = - new StoreMigrator( fileSystemRule.get(), pageCache, config, logService, legacyLogs ); - TransactionId actual = migrator.extractTransactionIdInformation( neoStore, storeDir, txId ); - - // then - assertEquals( expected, actual ); - } - @Test public void shouldGenerateTransactionInformationWhenLogsNotPresent() throws Exception { @@ -155,15 +121,12 @@ public void shouldGenerateTransactionInformationWhenLogsNotPresent() throws Exce neoStore.createNewFile(); Config config = mock( Config.class ); LogService logService = new SimpleLogService( NullLogProvider.getInstance(), NullLogProvider.getInstance() ); - LegacyLogs legacyLogs = mock( LegacyLogs.class ); // when // ... transaction info not in neo store assertEquals( FIELD_NOT_PRESENT, getRecord( pageCache, neoStore, LAST_TRANSACTION_ID ) ); assertEquals( FIELD_NOT_PRESENT, getRecord( pageCache, neoStore, LAST_TRANSACTION_CHECKSUM ) ); assertEquals( FIELD_NOT_PRESENT, getRecord( pageCache, neoStore, LAST_TRANSACTION_COMMIT_TIMESTAMP ) ); - // ... and transaction not in log - when( legacyLogs.getTransactionInformation( storeDir, txId ) ).thenReturn( Optional.empty() ); // ... and with migrator StoreMigrator migrator = new StoreMigrator( fileSystemRule.get(), pageCache, config, logService ); TransactionId actual = migrator.extractTransactionIdInformation( neoStore, storeDir, txId ); @@ -184,15 +147,12 @@ public void shouldGenerateTransactionInformationWhenLogsAreEmpty() throws Except neoStore.createNewFile(); Config config = mock( Config.class ); LogService logService = new SimpleLogService( NullLogProvider.getInstance(), NullLogProvider.getInstance() ); - LegacyLogs legacyLogs = mock( LegacyLogs.class ); // when // ... transaction info not in neo store assertEquals( FIELD_NOT_PRESENT, getRecord( pageCache, neoStore, LAST_TRANSACTION_ID ) ); assertEquals( FIELD_NOT_PRESENT, getRecord( pageCache, neoStore, LAST_TRANSACTION_CHECKSUM ) ); assertEquals( FIELD_NOT_PRESENT, getRecord( pageCache, neoStore, LAST_TRANSACTION_COMMIT_TIMESTAMP ) ); - // ... and transaction not in log - when( legacyLogs.getTransactionInformation( storeDir, txId ) ).thenReturn( Optional.empty() ); // ... and with migrator StoreMigrator migrator = new StoreMigrator( fileSystemRule.get(), pageCache, config, logService ); TransactionId actual = migrator.extractTransactionIdInformation( neoStore, storeDir, txId ); diff --git a/community/kernel/src/test/java/org/neo4j/kernel/impl/transaction/command/PhysicalLogCommandReaderV2_1Test.java b/community/kernel/src/test/java/org/neo4j/kernel/impl/transaction/command/PhysicalLogCommandReaderV2_1Test.java deleted file mode 100644 index 49e1b25dfd8c6..0000000000000 --- a/community/kernel/src/test/java/org/neo4j/kernel/impl/transaction/command/PhysicalLogCommandReaderV2_1Test.java +++ /dev/null @@ -1,94 +0,0 @@ -/* - * Copyright (c) 2002-2017 "Neo Technology," - * Network Engine for Objects in Lund AB [http://neotechnology.com] - * - * This file is part of Neo4j. - * - * Neo4j is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ -package org.neo4j.kernel.impl.transaction.command; - -import org.junit.Test; - -import org.neo4j.helpers.collection.Iterables; -import org.neo4j.kernel.impl.store.PropertyStore; -import org.neo4j.kernel.impl.store.PropertyType; -import org.neo4j.kernel.impl.store.record.DynamicRecord; -import org.neo4j.kernel.impl.store.record.PropertyBlock; -import org.neo4j.kernel.impl.store.record.PropertyRecord; -import org.neo4j.kernel.impl.transaction.command.Command.PropertyCommand; -import org.neo4j.kernel.impl.transaction.log.InMemoryClosableChannel; - -import static org.junit.Assert.assertArrayEquals; -import static org.junit.Assert.assertEquals; -import static org.neo4j.kernel.impl.store.PropertyType.STRING; - -public class PhysicalLogCommandReaderV2_1Test -{ - @Test - public void shouldReadPropertyCommandWithDeletedDynamicRecords() throws Exception - { - // GIVEN - PhysicalLogCommandReaderV2_1 reader = new PhysicalLogCommandReaderV2_1(); - InMemoryClosableChannel data = new InMemoryClosableChannel(); - long id = 5; - int keyId = 6; - byte[] data1 = new byte[] {1, 2, 3, 4, 5}; - byte[] data2 = new byte[] {6, 7, 8, 9, 10}; - long value = 1234; - PropertyRecord property = new PropertyRecord( id ); - property.setInUse( true ); - property.addPropertyBlock( propertyBlockWithSomeDynamicRecords( keyId, STRING, value, data1, data2 ) ); - property.addDeletedRecord( dynamicRecord( false, null, STRING.intValue() ) ); - property.addDeletedRecord( dynamicRecord( false, null, STRING.intValue() ) ); - - // WHEN - new PropertyCommand( new PropertyRecord( id ), property ).serialize( data ); - - // THEN - PropertyCommand readCommand = (PropertyCommand) reader.read( data ); - PropertyRecord readRecord = readCommand.getAfter(); - assertEquals( id, readRecord.getId() ); - PropertyBlock readBlock = Iterables.single( readRecord ); - assertArrayEquals( data1, readBlock.getValueRecords().get( 0 ).getData() ); - assertArrayEquals( data2, readBlock.getValueRecords().get( 1 ).getData() ); - assertEquals( 2, readRecord.getDeletedRecords().size() ); - } - - private long dynamicRecordId = 1; - - private DynamicRecord dynamicRecord( boolean inUse, byte[] data, int type ) - { - DynamicRecord record = new DynamicRecord( dynamicRecordId++ ); - record.setInUse( inUse, type ); - if ( data != null ) - { - record.setData( data ); - record.setLength( data.length ); - } - return record; - } - - private PropertyBlock propertyBlockWithSomeDynamicRecords( int keyId, PropertyType type, long value, - byte[]... dynamicRecordData ) - { - PropertyBlock block = new PropertyBlock(); - block.setSingleBlock( PropertyStore.singleBlockLongValue( keyId, type, value ) ); - for ( byte[] bytes : dynamicRecordData ) - { - block.addValueRecord( dynamicRecord( true, bytes, type.intValue() ) ); - } - return block; - } -} diff --git a/community/kernel/src/test/java/org/neo4j/kernel/impl/transaction/command/PhysicalLogCommandReadersTest.java b/community/kernel/src/test/java/org/neo4j/kernel/impl/transaction/command/PhysicalLogCommandReadersTest.java index 882f31e6b4a7d..cfb09114662fd 100644 --- a/community/kernel/src/test/java/org/neo4j/kernel/impl/transaction/command/PhysicalLogCommandReadersTest.java +++ b/community/kernel/src/test/java/org/neo4j/kernel/impl/transaction/command/PhysicalLogCommandReadersTest.java @@ -51,24 +51,6 @@ public class PhysicalLogCommandReadersTest private static final long FIRST_LOOP = 42; private static final long OWNING_NODE = 42; - @Test - public void readRelGroupWithHugeTypeInV2_0() - { - assertDoesNotKnowAboutRelGroups( new PhysicalLogCommandReaderV2_0() ); - } - - @Test - public void readRelGroupWithHugeTypeInV2_1() throws IOException - { - assertCanReadRelGroup( new PhysicalLogCommandReaderV2_1() ); - } - - @Test - public void readRelGroupWithHugeTypeInV2_2() throws IOException - { - assertCanReadRelGroup( new PhysicalLogCommandReaderV2_2() ); - } - @Test public void readRelGroupWithHugeTypeInV2_2_4() throws IOException { diff --git a/community/kernel/src/test/java/org/neo4j/kernel/impl/transaction/log/entry/LogEntryParserDispatcherV6Test.java b/community/kernel/src/test/java/org/neo4j/kernel/impl/transaction/log/entry/LogEntryParserDispatcherV6Test.java index db265e5d9130a..6865d16a777e1 100644 --- a/community/kernel/src/test/java/org/neo4j/kernel/impl/transaction/log/entry/LogEntryParserDispatcherV6Test.java +++ b/community/kernel/src/test/java/org/neo4j/kernel/impl/transaction/log/entry/LogEntryParserDispatcherV6Test.java @@ -155,30 +155,10 @@ public void shouldParseCheckPointEntry() throws IOException } @Test( expected = IllegalArgumentException.class ) - public void shouldThrowWhenParsingPrepareEntry() throws IOException + public void shouldThrowWhenParsingUnknownEntry() throws IOException { // when - version.entryParser( LogEntryByteCodes.TX_PREPARE ); - - // then - // it should throw exception - } - - @Test( expected = IllegalArgumentException.class ) - public void shouldThrowWhenParsingTwoPhaseCommitEntry() throws IOException - { - // when - version.entryParser( LogEntryByteCodes.TX_2P_COMMIT ); - - // then - // it should throw exception - } - - @Test( expected = IllegalArgumentException.class ) - public void shouldThrowWhenParsingDoneEntry() throws IOException - { - // when - version.entryParser( LogEntryByteCodes.DONE ); + version.entryParser( (byte)42 ); // unused, at lest for now // then // it should throw exception diff --git a/community/kernel/src/test/java/org/neo4j/kernel/impl/transaction/log/entry/LogEntryParserV2_1Test.java b/community/kernel/src/test/java/org/neo4j/kernel/impl/transaction/log/entry/LogEntryParserV2_1Test.java deleted file mode 100644 index 7c9f8316f79a5..0000000000000 --- a/community/kernel/src/test/java/org/neo4j/kernel/impl/transaction/log/entry/LogEntryParserV2_1Test.java +++ /dev/null @@ -1,212 +0,0 @@ -/* - * Copyright (c) 2002-2017 "Neo Technology," - * Network Engine for Objects in Lund AB [http://neotechnology.com] - * - * This file is part of Neo4j. - * - * Neo4j is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ -package org.neo4j.kernel.impl.transaction.log.entry; - -import org.junit.Test; - -import java.io.IOException; - -import org.neo4j.kernel.impl.storageengine.impl.recordstorage.RecordStorageCommandReaderFactory; -import org.neo4j.kernel.impl.store.record.NodeRecord; -import org.neo4j.kernel.impl.transaction.command.Command; -import org.neo4j.kernel.impl.transaction.log.InMemoryClosableChannel; -import org.neo4j.kernel.impl.transaction.log.LogPosition; -import org.neo4j.kernel.impl.transaction.log.LogPositionMarker; -import org.neo4j.storageengine.api.CommandReaderFactory; - -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertFalse; -import static org.junit.Assert.assertNull; -import static org.junit.Assert.assertTrue; - -public class LogEntryParserV2_1Test -{ - private final LogEntryVersion version = LogEntryVersion.V2_1; - private final CommandReaderFactory commandReader = new RecordStorageCommandReaderFactory(); - private final LogPositionMarker marker = new LogPositionMarker(); - private final LogPosition position = new LogPosition( 0, 37 ); - - @Test - public void shouldParseStartEntry() throws IOException - { - // given - final LogEntryStart start = new LogEntryStart( version, 1, 2, 3, 4, new byte[]{}, position ); - final InMemoryClosableChannel channel = new InMemoryClosableChannel(); - - // ignored part - channel.put( (byte) 1 ); // globalId length - channel.put( (byte) 2 ); // branchId length - channel.put( new byte[]{42}, 1 ); // globalId - channel.put( new byte[]{21, 12}, 2 ); // branchId - channel.putInt( 123 ); // identifier - channel.putInt( 456 ); // formatId - // actual read data - channel.putInt( start.getMasterId() ); - channel.putInt( start.getLocalId() ); - channel.putLong( start.getTimeWritten() ); - channel.putLong( start.getLastCommittedTxWhenTransactionStarted() ); - - channel.getCurrentPosition( marker ); - - // when - final LogEntryParser parser = version.entryParser( LogEntryByteCodes.TX_START ); - final LogEntry logEntry = parser.parse( version, channel, marker, commandReader ); - - // then - assertEquals( start, entryOf( logEntry ) ); - assertFalse( parser.skip() ); - } - - private LogEntry entryOf( LogEntry logEntry ) - { - return logEntry instanceof IdentifiableLogEntry ? ((IdentifiableLogEntry)logEntry).getEntry() : logEntry; - } - - @Test - public void shouldParseOnePhaseCommitEntry() throws IOException - { - // given - final LogEntryCommit commit = new OnePhaseCommit( version, 42, 21 ); - final InMemoryClosableChannel channel = new InMemoryClosableChannel(); - - // ignored data - channel.putInt( 123 ); // identifier - // actual read data - channel.putLong( commit.getTxId() ); - channel.putLong( commit.getTimeWritten() ); - - channel.getCurrentPosition( marker ); - - // when - final LogEntryParser parser = version.entryParser( LogEntryByteCodes.TX_1P_COMMIT ); - final LogEntry logEntry = parser.parse( version, channel, marker, commandReader ); - - // then - assertEquals( commit, entryOf( logEntry ) ); - assertFalse( parser.skip() ); - } - - @Test - public void shouldParseTwoPhaseCommitEntryAndMapThemIntoOnePhaseCommit() throws IOException - { - // given - final LogEntryCommit commit = new OnePhaseCommit( version, 42, 21 ); - final InMemoryClosableChannel channel = new InMemoryClosableChannel(); - - // ignored data - channel.putInt( 123 ); // identifier - // actual read data - channel.putLong( commit.getTxId() ); - channel.putLong( commit.getTimeWritten() ); - - channel.getCurrentPosition( marker ); - - // when - final LogEntryParser parser = version.entryParser( LogEntryByteCodes.TX_2P_COMMIT ); - final LogEntry logEntry = parser.parse( version, channel, marker, commandReader ); - - // then - assertEquals( commit, entryOf( logEntry ) ); - assertFalse( parser.skip() ); - } - - @Test - public void shouldParseCommandsUsingAGivenFactory() throws IOException - { - // given - final Command.NodeCommand nodeCommand = new Command.NodeCommand( new NodeRecord( 0 ), new NodeRecord( 0 ) ); - final LogEntryCommand command = new LogEntryCommand( version, nodeCommand ); - final InMemoryClosableChannel channel = new InMemoryClosableChannel(); - - // ignored data - channel.putInt( 123 ); // identifier - // actual read data - nodeCommand.serialize( channel ); - - channel.getCurrentPosition( marker ); - - // when - final LogEntryParser parser = version.entryParser( LogEntryByteCodes.COMMAND ); - final LogEntry logEntry = parser.parse( version, channel, marker, commandReader ); - - // then - assertEquals( command, entryOf( logEntry ) ); - assertFalse( parser.skip() ); - } - - @Test - public void shouldParseEmptyEntry() throws IOException - { - // when - final LogEntryParser parser = version.entryParser( LogEntryByteCodes.EMPTY ); - final LogEntry logEntry = parser.parse( version, new InMemoryClosableChannel(), marker, commandReader ); - - // then - assertNull( logEntry ); - assertFalse( parser.skip() ); - } - - @Test - public void shouldParsePrepareEntry() throws IOException - { - // given - final byte nextByte = (byte) 7; - final InMemoryClosableChannel channel = new InMemoryClosableChannel(); - // ignored - channel.putInt( 123 ); // identifier - channel.putLong( 456 ); // timeWritten - // data available after - channel.put( nextByte ); - - channel.getCurrentPosition( marker ); - - // when - final LogEntryParser parser = version.entryParser( LogEntryByteCodes.TX_PREPARE ); - final LogEntry logEntry = parser.parse( version, channel, marker, commandReader ); - - // then - assertNull( logEntry ); - assertTrue( parser.skip() ); - assertEquals( nextByte, channel.get() ); - } - - @Test - public void shouldParseDoneEntry() throws IOException - { - // given - final byte nextByte = (byte) 7; - final InMemoryClosableChannel channel = new InMemoryClosableChannel(); - // ignored - channel.putInt( 123 ); // identifier - // data available after - channel.put( nextByte ); - - channel.getCurrentPosition( marker ); - - // when - final LogEntryParser parser = version.entryParser( LogEntryByteCodes.DONE ); - final LogEntry logEntry = parser.parse( version, channel, marker, commandReader ); - - // then - assertNull( logEntry ); - assertTrue( parser.skip() ); - assertEquals( nextByte, channel.get() ); - } -} diff --git a/community/kernel/src/test/java/org/neo4j/kernel/impl/transaction/log/entry/LogEntryParserV2_2Test.java b/community/kernel/src/test/java/org/neo4j/kernel/impl/transaction/log/entry/LogEntryParserV2_2Test.java deleted file mode 100644 index 72ab032f9d894..0000000000000 --- a/community/kernel/src/test/java/org/neo4j/kernel/impl/transaction/log/entry/LogEntryParserV2_2Test.java +++ /dev/null @@ -1,139 +0,0 @@ -/* - * Copyright (c) 2002-2017 "Neo Technology," - * Network Engine for Objects in Lund AB [http://neotechnology.com] - * - * This file is part of Neo4j. - * - * Neo4j is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ -package org.neo4j.kernel.impl.transaction.log.entry; - -import org.junit.Test; - -import java.io.IOException; - -import org.neo4j.kernel.impl.storageengine.impl.recordstorage.RecordStorageCommandReaderFactory; -import org.neo4j.kernel.impl.store.record.NodeRecord; -import org.neo4j.kernel.impl.transaction.command.Command; -import org.neo4j.kernel.impl.transaction.log.InMemoryClosableChannel; -import org.neo4j.kernel.impl.transaction.log.LogPosition; -import org.neo4j.kernel.impl.transaction.log.LogPositionMarker; -import org.neo4j.storageengine.api.CommandReaderFactory; - -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertFalse; -import static org.junit.Assert.assertNull; -import static org.junit.Assert.fail; - -public class LogEntryParserV2_2Test -{ - private final LogEntryVersion version = LogEntryVersion.V2_2; - private final CommandReaderFactory commandReader = new RecordStorageCommandReaderFactory(); - private final LogPositionMarker marker = new LogPositionMarker(); - private final LogPosition position = new LogPosition( 0, 29 ); - - @Test - public void shouldParseStartEntry() throws IOException - { - // given - final LogEntryStart start = new LogEntryStart( version, 1, 2, 3, 4, new byte[]{5}, position ); - final InMemoryClosableChannel channel = new InMemoryClosableChannel(); - - channel.putInt( start.getMasterId() ); - channel.putInt( start.getLocalId() ); - channel.putLong( start.getTimeWritten() ); - channel.putLong( start.getLastCommittedTxWhenTransactionStarted() ); - channel.putInt( start.getAdditionalHeader().length ); - channel.put( start.getAdditionalHeader(), start.getAdditionalHeader().length ); - - channel.getCurrentPosition( marker ); - - // when - final LogEntryParser parser = version.entryParser( LogEntryByteCodes.TX_START ); - final LogEntry logEntry = parser.parse( version, channel, marker, commandReader ); - - // then - assertEquals( start, logEntry ); - assertFalse( parser.skip() ); - } - - @Test - public void shouldParseOnePhaseCommitEntry() throws IOException - { - // given - final LogEntryCommit commit = new OnePhaseCommit( version, 42, 21 ); - final InMemoryClosableChannel channel = new InMemoryClosableChannel(); - - channel.putLong( commit.getTxId() ); - channel.putLong( commit.getTimeWritten() ); - - channel.getCurrentPosition( marker ); - - // when - final LogEntryParser parser = version.entryParser( LogEntryByteCodes.TX_1P_COMMIT ); - final LogEntry logEntry = parser.parse( version, channel, marker, commandReader ); - - // then - assertEquals( commit, logEntry ); - assertFalse( parser.skip() ); - } - - @Test - public void shouldParseCommandsUsingAGivenFactory() throws IOException - { - // given - Command.NodeCommand nodeCommand = new Command.NodeCommand( new NodeRecord( 0 ), new NodeRecord( 0 ) ); - final LogEntryCommand command = new LogEntryCommand( version, nodeCommand ); - final InMemoryClosableChannel channel = new InMemoryClosableChannel(); - - nodeCommand.serialize( channel ); - - channel.getCurrentPosition( marker ); - - // when - final LogEntryParser parser = version.entryParser( LogEntryByteCodes.COMMAND ); - final LogEntry logEntry = parser.parse( version, channel, marker, commandReader ); - - // then - assertEquals( command, logEntry ); - assertFalse( parser.skip() ); - } - - @Test - public void shouldParseEmptyEntry() throws IOException - { - // when - final LogEntryParser parser = version.entryParser( LogEntryByteCodes.EMPTY ); - final LogEntry logEntry = parser.parse( version, new InMemoryClosableChannel(), marker, commandReader ); - - // then - assertNull( logEntry ); - assertFalse( parser.skip() ); - } - - @Test - public void shouldThrowWhenParsingUnknownEntry() - { - // when - try - { - version.entryParser( LogEntryByteCodes.TX_PREPARE ); - fail( "Should have thrown" ); - } - catch ( IllegalArgumentException e ) - { - // Good - } - } -} diff --git a/community/kernel/src/test/java/org/neo4j/kernel/impl/transaction/log/entry/VersionAwareLogEntryReaderTest.java b/community/kernel/src/test/java/org/neo4j/kernel/impl/transaction/log/entry/VersionAwareLogEntryReaderTest.java index 33ce98432f0d2..304dbfb92915e 100644 --- a/community/kernel/src/test/java/org/neo4j/kernel/impl/transaction/log/entry/VersionAwareLogEntryReaderTest.java +++ b/community/kernel/src/test/java/org/neo4j/kernel/impl/transaction/log/entry/VersionAwareLogEntryReaderTest.java @@ -35,7 +35,6 @@ import static java.util.Collections.singletonList; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertNull; -import static org.junit.Assert.assertTrue; public class VersionAwareLogEntryReaderTest { @@ -173,204 +172,6 @@ public void shouldReturnNullWhenNotEnoughDataInTheChannel() throws IOException assertNull( logEntry ); } - @Test - public void shouldParseOldStartEntry() throws IOException - { - // given - LogEntryVersion version = LogEntryVersion.V2_1; - final InMemoryClosableChannel channel = new InMemoryClosableChannel(); - final LogEntryStart start = new LogEntryStart( 1, 2, 3, 4, new byte[]{}, new LogPosition( 0, 37 ) ); - - channel.put( version.byteCode() ); - channel.put( LogEntryByteCodes.TX_START ); - // ignored data - channel.put( (byte) 1 ); // globalId length - channel.put( (byte) 0 ); // branchId length - channel.put( new byte[]{7}, 1 ); // globalId - channel.put( new byte[]{}, 0 ); // branchId - channel.putInt( 123 ); // identifier - channel.putInt( 456 ); // formatId - // actually used data - channel.putInt( start.getMasterId() ); - channel.putInt( start.getLocalId() ); - channel.putLong( start.getTimeWritten() ); - channel.putLong( start.getLastCommittedTxWhenTransactionStarted() ); - - // when - final LogEntry logEntry = logEntryReader.readLogEntry( channel ); - - // then - assertTrue( logEntry instanceof IdentifiableLogEntry ); - assertEquals( start, ((IdentifiableLogEntry) logEntry).getEntry() ); - } - - @Test - public void shouldParseOldOnePhaseCommit() throws IOException - { - // given - LogEntryVersion version = LogEntryVersion.V2_1; - final InMemoryClosableChannel channel = new InMemoryClosableChannel(); - final OnePhaseCommit commit = new OnePhaseCommit( 42, 456 ); - - channel.put( version.byteCode() ); - channel.put( LogEntryByteCodes.TX_1P_COMMIT ); - // ignored data - channel.putInt( 123 ); // identifier - // actually used data - channel.putLong( commit.getTxId() ); - channel.putLong( commit.getTimeWritten() ); - - // when - final LogEntry logEntry = logEntryReader.readLogEntry( channel ); - - // then - assertTrue( logEntry instanceof IdentifiableLogEntry ); - assertEquals( commit, ((IdentifiableLogEntry) logEntry).getEntry() ); - } - - @Test - public void shouldParseOldTwoPhaseCommit() throws IOException - { - // given - LogEntryVersion version = LogEntryVersion.V2_1; - final InMemoryClosableChannel channel = new InMemoryClosableChannel(); - final OnePhaseCommit commit = new OnePhaseCommit( 42, 456 ); - - channel.put( version.byteCode() ); - channel.put( LogEntryByteCodes.TX_2P_COMMIT ); - // ignored data - channel.putInt( 123 ); // identifier - // actually used data - channel.putLong( commit.getTxId() ); - channel.putLong( commit.getTimeWritten() ); - - // when - final LogEntry logEntry = logEntryReader.readLogEntry( channel ); - - // then - assertTrue( logEntry instanceof IdentifiableLogEntry ); - assertEquals( commit, ((IdentifiableLogEntry) logEntry).getEntry() ); - } - - @Test - public void shouldParseOldPrepareSkipItAndReadTheOneAfter() throws IOException - { - // given - LogEntryVersion version = LogEntryVersion.V2_1; - final InMemoryClosableChannel channel = new InMemoryClosableChannel(); - final OnePhaseCommit commit = new OnePhaseCommit( 42, 456 ); - - // PREPARE - channel.put( version.byteCode() ); - channel.put( LogEntryByteCodes.TX_PREPARE ); - // ignored data - channel.putInt( 123 ); // identifier - channel.putLong( 456 ); // timewritten - // 2P COMMIT - channel.put( version.byteCode() ); - channel.put( LogEntryByteCodes.TX_2P_COMMIT ); - // ignored data - channel.putInt( 123 ); // identifier - // actually used data - channel.putLong( commit.getTxId() ); - channel.putLong( commit.getTimeWritten() ); - - // when - final LogEntry logEntry = logEntryReader.readLogEntry( channel ); - - // then - assertTrue( logEntry instanceof IdentifiableLogEntry ); - assertEquals( commit, ((IdentifiableLogEntry) logEntry).getEntry() ); - } - - @Test - public void shouldParseOldDoneSkipItAndReadTheOneAfter() throws IOException - { - // given - LogEntryVersion version = LogEntryVersion.V2_1; - final InMemoryClosableChannel channel = new InMemoryClosableChannel(); - final OnePhaseCommit commit = new OnePhaseCommit( 42, 456 ); - - // PREPARE - channel.put( version.byteCode() ); - channel.put( LogEntryByteCodes.DONE ); - // ignored data - channel.putInt( 123 ); // identifier - // 2P COMMIT - channel.put( version.byteCode() ); - channel.put( LogEntryByteCodes.TX_2P_COMMIT ); - // ignored data - channel.putInt( 123 ); // identifier - // actually used data - channel.putLong( commit.getTxId() ); - channel.putLong( commit.getTimeWritten() ); - - // when - final LogEntry logEntry = logEntryReader.readLogEntry( channel ); - - // then - assertTrue( logEntry instanceof IdentifiableLogEntry ); - assertEquals( commit, ((IdentifiableLogEntry) logEntry).getEntry() ); - } - - @Test - public void shouldParseAnOldCommandLogEntry() throws IOException - { - // given - LogEntryVersion version = LogEntryVersion.V2_1; - Command.NodeCommand nodeCommand = new Command.NodeCommand( new NodeRecord( 10 ), new NodeRecord( 10 ) ); - final LogEntryCommand command = new LogEntryCommand( version, nodeCommand ); - final InMemoryClosableChannel channel = new InMemoryClosableChannel(); - - channel.put( version.byteCode() ); - channel.put( LogEntryByteCodes.COMMAND ); - // ignored data - channel.putInt( 42 ); // identifier ignored - // actual used data - nodeCommand.serialize( channel ); - - // when - final LogEntry logEntry = logEntryReader.readLogEntry( channel ); - - // then - assertTrue( logEntry instanceof IdentifiableLogEntry ); - assertEquals( command, ((IdentifiableLogEntry) logEntry).getEntry() ); - } - - @Test - public void shouldReturnNullWhenThereIsNoCommandOldVersion() throws IOException - { - // given - LogEntryVersion version = LogEntryVersion.V2_1; - final InMemoryClosableChannel channel = new InMemoryClosableChannel(); - - channel.put( version.byteCode() ); - channel.put( LogEntryByteCodes.COMMAND ); - channel.put( NeoCommandType.NONE ); - - // when - final LogEntry logEntry = logEntryReader.readLogEntry( channel ); - - // then - assertNull( logEntry ); - } - - @Test - public void shouldParseOldLogEntryEmptyANdReturnNull() throws IOException - { - // given - LogEntryVersion version = LogEntryVersion.V2_1; - final InMemoryClosableChannel channel = new InMemoryClosableChannel(); - channel.put( version.byteCode() ); - channel.put( LogEntryByteCodes.EMPTY ); - - // when - final LogEntry logEntry = logEntryReader.readLogEntry( channel ); - - // then - assertNull( logEntry ); - } - @Test public void shouldParseStreamOfZerosAsEmptyLogEntries() throws Exception { diff --git a/community/kernel/src/test/java/org/neo4j/kernel/impl/transaction/state/RelationshipGroupCommandV2_2Test.java b/community/kernel/src/test/java/org/neo4j/kernel/impl/transaction/state/RelationshipGroupCommandV2_2Test.java deleted file mode 100644 index 40370a18cdc3b..0000000000000 --- a/community/kernel/src/test/java/org/neo4j/kernel/impl/transaction/state/RelationshipGroupCommandV2_2Test.java +++ /dev/null @@ -1,82 +0,0 @@ -/* - * Copyright (c) 2002-2017 "Neo Technology," - * Network Engine for Objects in Lund AB [http://neotechnology.com] - * - * This file is part of Neo4j. - * - * Neo4j is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ -package org.neo4j.kernel.impl.transaction.state; - -import org.junit.Test; - -import java.io.IOException; - -import org.neo4j.kernel.impl.store.record.RelationshipGroupRecord; -import org.neo4j.kernel.impl.transaction.command.Command; -import org.neo4j.kernel.impl.transaction.command.PhysicalLogCommandReaderV2_2; -import org.neo4j.kernel.impl.transaction.log.InMemoryClosableChannel; -import org.neo4j.storageengine.api.CommandReader; - -import static org.hamcrest.MatcherAssert.assertThat; -import static org.hamcrest.core.IsEqual.equalTo; - -public class RelationshipGroupCommandV2_2Test -{ - @Test - public void shouldSerializeAndDeserializeUnusedRecords() throws Exception - { - // Given - RelationshipGroupRecord before = new RelationshipGroupRecord( 10, 12, 13, 14, 15, 16, 17, true ); - RelationshipGroupRecord after = new RelationshipGroupRecord( 10, 12 ); - after.setInUse( false ); - - // When - assertSerializationWorksFor( new Command.RelationshipGroupCommand( before, after ) ); - } - - @Test - public void shouldSerializeCreatedRecord() throws Exception - { - // Given - RelationshipGroupRecord before = new RelationshipGroupRecord( 10, 12 ); - before.setInUse( false ); - RelationshipGroupRecord after = new RelationshipGroupRecord( 10, 12, 13, 14, 15, 16, 17, true ); - after.setCreated(); - - // When - assertSerializationWorksFor( new Command.RelationshipGroupCommand( before, after ) ); - } - - private void assertSerializationWorksFor( Command.RelationshipGroupCommand cmd ) throws IOException - { - InMemoryClosableChannel channel = new InMemoryClosableChannel(); - cmd.serialize( channel ); - - CommandReader commandReader = new PhysicalLogCommandReaderV2_2(); - Command.RelationshipGroupCommand result = (Command.RelationshipGroupCommand) commandReader.read( channel ); - - RelationshipGroupRecord recordBefore = cmd.getBefore(); - RelationshipGroupRecord recordAfter = result.getAfter(); - - // Then - assertThat( recordBefore.getFirstIn(), equalTo( recordAfter.getFirstIn() ) ); - assertThat( recordBefore.getFirstOut(), equalTo( recordAfter.getFirstOut() ) ); - assertThat( recordBefore.getFirstLoop(), equalTo( recordAfter.getFirstLoop() ) ); - assertThat( recordBefore.getNext(), equalTo( recordAfter.getNext() ) ); - assertThat( recordBefore.getOwningNode(), equalTo( recordAfter.getOwningNode() ) ); - assertThat( recordBefore.getPrev(), equalTo( recordAfter.getPrev() ) ); - assertThat( recordBefore.getType(), equalTo( recordAfter.getType() ) ); - } -} diff --git a/community/kernel/src/test/java/org/neo4j/kernel/impl/transaction/state/SchemaRuleCommandTest.java b/community/kernel/src/test/java/org/neo4j/kernel/impl/transaction/state/SchemaRuleCommandTest.java index b100485547e79..8ceb4a5a1f921 100644 --- a/community/kernel/src/test/java/org/neo4j/kernel/impl/transaction/state/SchemaRuleCommandTest.java +++ b/community/kernel/src/test/java/org/neo4j/kernel/impl/transaction/state/SchemaRuleCommandTest.java @@ -45,6 +45,7 @@ import org.neo4j.kernel.impl.store.record.DynamicRecord; import org.neo4j.kernel.impl.store.record.IndexRule; import org.neo4j.kernel.impl.store.record.SchemaRecord; +import org.neo4j.kernel.impl.transaction.command.BaseCommandReader; import org.neo4j.kernel.impl.transaction.command.Command; import org.neo4j.kernel.impl.transaction.command.Command.SchemaRuleCommand; import org.neo4j.kernel.impl.transaction.command.CommandHandlerContract; @@ -52,7 +53,7 @@ import org.neo4j.kernel.impl.transaction.command.IndexUpdatesWork; import org.neo4j.kernel.impl.transaction.command.LabelUpdateWork; import org.neo4j.kernel.impl.transaction.command.NeoStoreBatchTransactionApplier; -import org.neo4j.kernel.impl.transaction.command.PhysicalLogCommandReaderV2_2; +import org.neo4j.kernel.impl.transaction.command.PhysicalLogCommandReaderV3_0_2; import org.neo4j.kernel.impl.transaction.log.InMemoryClosableChannel; import org.neo4j.kernel.impl.transaction.log.PhysicalTransactionRepresentation; import org.neo4j.storageengine.api.TransactionApplicationMode; @@ -91,7 +92,7 @@ public class SchemaRuleCommandTest labelScanStoreSynchronizer, indexUpdatesSync, mock( NodeStore.class ), new PropertyPhysicalToLogicalConverter( propertyStore ), TransactionApplicationMode.INTERNAL ); - private final PhysicalLogCommandReaderV2_2 reader = new PhysicalLogCommandReaderV2_2(); + private final BaseCommandReader reader = new PhysicalLogCommandReaderV3_0_2(); private final IndexRule rule = IndexRule.indexRule( id, IndexDescriptorFactory.forLabel( labelId, propertyKey ), PROVIDER_DESCRIPTOR ); diff --git a/community/neo4j/src/test/java/upgrade/StoreUpgraderTest.java b/community/neo4j/src/test/java/upgrade/StoreUpgraderTest.java index 2297adb8ec100..a558b972177c1 100644 --- a/community/neo4j/src/test/java/upgrade/StoreUpgraderTest.java +++ b/community/neo4j/src/test/java/upgrade/StoreUpgraderTest.java @@ -29,14 +29,12 @@ import org.mockito.Mockito; import java.io.File; -import java.io.FilenameFilter; import java.io.IOException; import java.util.Arrays; import java.util.Collection; import java.util.List; import org.neo4j.graphdb.factory.GraphDatabaseSettings; -import org.neo4j.graphdb.mockfs.DelegatingFileSystemAbstraction; import org.neo4j.io.fs.FileSystemAbstraction; import org.neo4j.io.pagecache.PageCache; import org.neo4j.kernel.api.index.SchemaIndexProvider; @@ -47,7 +45,6 @@ import org.neo4j.kernel.impl.store.NeoStores; import org.neo4j.kernel.impl.store.StoreFactory; import org.neo4j.kernel.impl.store.format.RecordFormats; -import org.neo4j.kernel.impl.store.format.standard.MetaDataRecordFormat; import org.neo4j.kernel.impl.store.format.standard.Standard; import org.neo4j.kernel.impl.store.format.standard.StandardV2_3; import org.neo4j.kernel.impl.storemigration.StoreMigrationParticipant; @@ -56,7 +53,6 @@ import org.neo4j.kernel.impl.storemigration.StoreVersionCheck; import org.neo4j.kernel.impl.storemigration.UpgradableDatabase; import org.neo4j.kernel.impl.storemigration.UpgradeNotAllowedByConfigurationException; -import org.neo4j.kernel.impl.storemigration.legacylogs.LegacyLogFilenames; import org.neo4j.kernel.impl.storemigration.monitoring.MigrationProgressMonitor; import org.neo4j.kernel.impl.storemigration.monitoring.SilentMigrationProgressMonitor; import org.neo4j.kernel.impl.storemigration.monitoring.VisibleMigrationProgressMonitor; @@ -71,11 +67,9 @@ import org.neo4j.test.rule.fs.DefaultFileSystemRule; import static java.util.concurrent.TimeUnit.MINUTES; -import static org.hamcrest.Matchers.containsString; import static org.hamcrest.Matchers.emptyCollectionOf; import static org.hamcrest.Matchers.equalTo; import static org.hamcrest.Matchers.greaterThan; -import static org.hamcrest.Matchers.instanceOf; import static org.hamcrest.Matchers.is; import static org.hamcrest.Matchers.not; import static org.junit.Assert.assertEquals; @@ -83,7 +77,6 @@ import static org.junit.Assert.assertThat; import static org.junit.Assert.assertTrue; import static org.junit.Assert.fail; -import static org.junit.internal.matchers.ThrowableMessageMatcher.hasMessage; import static org.mockito.Matchers.any; import static org.mockito.Matchers.eq; import static org.mockito.Mockito.verify; @@ -134,56 +127,6 @@ public void prepareDb() throws IOException prepareSampleDatabase( version, fileSystem, dbDirectory, prepareDirectory ); } - @Test - public void failMigrationWhenFailDuringTransactionInformationRetrieval() throws IOException - { - File storeDirectory = directory.graphDbDir(); - File prepare = directory.directory( "prepare" ); - FileSystemAbstraction fs = new DelegatingFileSystemAbstraction( fileSystem ) - { - @Override - public File[] listFiles( File directory, FilenameFilter filter ) - { - if ( filter == LegacyLogFilenames.versionedLegacyLogFilesFilter ) - { - sneakyThrow( new IOException( "Enforced IO Exception Fail to open file" ) ); - } - return super.listFiles( directory, filter ); - } - }; - - prepareSampleDatabase( version, fs, storeDirectory, prepare ); - // and a state of the migration saying that it has done the actual migration - PageCache pageCache = pageCacheRule.getPageCache( fs ); - // remove metadata store record to force tx info lookup in tx logs - MetaDataStore.setRecord( pageCache, new File( storeDirectory, MetaDataStore.DEFAULT_NAME ), - MetaDataStore.Position.LAST_TRANSACTION_COMMIT_TIMESTAMP, MetaDataRecordFormat.FIELD_NOT_PRESENT ); - - UpgradableDatabase upgradableDatabase = new UpgradableDatabase( fs, new StoreVersionCheck( pageCache ), - getRecordFormats() ) - { - @Override - public RecordFormats checkUpgradeable( File storeDirectory ) - { - return getRecordFormats(); - } - }; - SilentMigrationProgressMonitor progressMonitor = new SilentMigrationProgressMonitor(); - - StoreMigrator defaultMigrator = new StoreMigrator( fs, pageCache, getTuningConfig(), NullLogService.getInstance() - - ); - StoreUpgrader upgrader = new StoreUpgrader( upgradableDatabase, progressMonitor, allowMigrateConfig, fs, - pageCache, NullLogProvider.getInstance() ); - upgrader.addParticipant( defaultMigrator ); - - expectedException.expect( UnableToUpgradeException.class ); - expectedException.expectCause( instanceOf( IOException.class ) ); - expectedException.expectCause( hasMessage( containsString( "Enforced IO Exception Fail to open file" ) ) ); - - upgrader.migrateIfNeeded( storeDirectory ); - } - @Test public void shouldHaltUpgradeIfUpgradeConfigurationVetoesTheProcess() throws IOException {