Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Allows for optional lenient reading of broken transaction log entries
Disabled by default and can only be enabled in DumpLogicalLog for the time being. Very useful when coming across a transaction log has broken entries or bad sections in the file. Failing to read an entry will revert back to start of previous read and one byte forward and try again. This will continue until next successful read of a log entry happens. Getting to a successful read after a bad secion will perform additional checks so that data in the read log entry makes sense. These checks are made on transaction id and time stamps and similar data fields.
- Loading branch information
Showing
8 changed files
with
307 additions
and
25 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
60 changes: 60 additions & 0 deletions
60
...nel/src/main/java/org/neo4j/kernel/impl/transaction/log/entry/InvalidLogEntryHandler.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,60 @@ | ||
/* | ||
* 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 <http://www.gnu.org/licenses/>. | ||
*/ | ||
package org.neo4j.kernel.impl.transaction.log.entry; | ||
|
||
import org.neo4j.kernel.impl.transaction.log.LogPosition; | ||
|
||
/** | ||
* Decides what happens to invalid log entries read by {@link LogEntryReader}. | ||
*/ | ||
public interface InvalidLogEntryHandler | ||
{ | ||
/** | ||
* Allows no invalid log entries. | ||
*/ | ||
public static final InvalidLogEntryHandler STRICT = new InvalidLogEntryHandler() | ||
{ | ||
}; | ||
|
||
/** | ||
* Log entry couldn't be read correctly. Could be invalid log entry in the log. | ||
* | ||
* @param e error during reading a log entry. | ||
* @param position {@link LogPosition} of the start of the log entry attempted to be read. | ||
* @return {@code true} if this error is accepted, otherwise {@code false} which means the exception | ||
* causing this will be thrown by the caller. | ||
*/ | ||
default boolean handleInvalidEntry( Exception e, LogPosition position ) | ||
{ // consider invalid by default | ||
return false; | ||
} | ||
|
||
/** | ||
* Tells this handler that, given that there were invalid entries, handler thinks they are OK | ||
* to skip and that one or more entries after a bad section could be read then a certain number | ||
* of bytes contained invalid log data and were therefore skipped. Log entry reading continues | ||
* after this call. | ||
* | ||
* @param bytesSkipped number of bytes skipped. | ||
*/ | ||
default void bytesSkipped( long bytesSkipped ) | ||
{ // do nothing by default | ||
} | ||
} |
87 changes: 87 additions & 0 deletions
87
...nity/kernel/src/main/java/org/neo4j/kernel/impl/transaction/log/entry/LogEntrySanity.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,87 @@ | ||
/* | ||
* 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 <http://www.gnu.org/licenses/>. | ||
*/ | ||
package org.neo4j.kernel.impl.transaction.log.entry; | ||
|
||
import java.util.concurrent.TimeUnit; | ||
|
||
import org.neo4j.kernel.impl.transaction.log.TransactionIdStore; | ||
|
||
import static java.lang.Math.abs; | ||
import static java.lang.System.currentTimeMillis; | ||
|
||
/** | ||
* Sanity checking for read {@link LogEntry log entries}. | ||
*/ | ||
class LogEntrySanity | ||
{ | ||
private static final long UNREASONABLY_LONG_TIME = TimeUnit.DAYS.toMillis( 30 * 356 /*years*/ ); | ||
private static final int UNREASONABLY_HIGH_SERVER_ID = 10_000_000; | ||
|
||
static boolean logEntryMakesSense( LogEntry entry ) | ||
{ | ||
if ( entry == null ) | ||
{ | ||
return false; | ||
} | ||
|
||
if ( entry instanceof IdentifiableLogEntry ) | ||
{ | ||
IdentifiableLogEntry iEntry = (IdentifiableLogEntry) entry; | ||
entry = iEntry.getEntry(); | ||
} | ||
|
||
if ( entry instanceof LogEntryStart ) | ||
{ | ||
return startEntryMakesSense( (LogEntryStart) entry ); | ||
} | ||
else if ( entry instanceof LogEntryCommit ) | ||
{ | ||
return commitEntryMakesSense( (LogEntryCommit) entry ); | ||
} | ||
return true; | ||
} | ||
|
||
static boolean commitEntryMakesSense( LogEntryCommit entry ) | ||
{ | ||
return timeMakesSense( entry.getTimeWritten() ) && transactionIdMakesSense( entry ); | ||
} | ||
|
||
private static boolean transactionIdMakesSense( LogEntryCommit entry ) | ||
{ | ||
return entry.getTxId() > TransactionIdStore.BASE_TX_ID; | ||
} | ||
|
||
static boolean startEntryMakesSense( LogEntryStart entry ) | ||
{ | ||
return serverIdMakesSense( entry.getLocalId() ) && | ||
serverIdMakesSense( entry.getMasterId() ) && | ||
timeMakesSense( entry.getTimeWritten() ); | ||
} | ||
|
||
private static boolean serverIdMakesSense( int serverId ) | ||
{ | ||
return serverId >= 0 && serverId < UNREASONABLY_HIGH_SERVER_ID; | ||
} | ||
|
||
static boolean timeMakesSense( long time ) | ||
{ | ||
return abs( currentTimeMillis() - time ) < UNREASONABLY_LONG_TIME; | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.