use of org.neo4j.kernel.impl.transaction.log.LogicalTransactionStore in project neo4j by neo4j.
the class TxPullRequestHandlerTest method shouldNotStreamTxsAndReportErrorIfTheLocalDatabaseIsNotAvailable.
@Test
public void shouldNotStreamTxsAndReportErrorIfTheLocalDatabaseIsNotAvailable() throws Exception {
// given
StoreId storeId = new StoreId(1, 2, 3, 4);
TransactionIdStore transactionIdStore = mock(TransactionIdStore.class);
when(transactionIdStore.getLastCommittedTransactionId()).thenReturn(15L);
LogicalTransactionStore logicalTransactionStore = mock(LogicalTransactionStore.class);
TxPullRequestHandler txPullRequestHandler = new TxPullRequestHandler(new CatchupServerProtocol(), () -> storeId, () -> false, () -> transactionIdStore, () -> logicalTransactionStore, BATCH_SIZE, new Monitors(), logProvider);
// when
txPullRequestHandler.channelRead0(context, new TxPullRequest(1, storeId));
// then
verify(context, never()).write(ResponseMessageType.TX);
verify(context).write(ResponseMessageType.TX_STREAM_FINISHED);
verify(context).write(new TxStreamFinishedResponse(E_STORE_UNAVAILABLE, 15L));
logProvider.assertAtLeastOnce(inLog(TxPullRequestHandler.class).info("Failed to serve TxPullRequest for tx %d because the local database is unavailable.", 2L));
}
use of org.neo4j.kernel.impl.transaction.log.LogicalTransactionStore in project neo4j by neo4j.
the class TxPullRequestHandlerTest method shouldRespondWithBatchOfTransactions.
@Test
public void shouldRespondWithBatchOfTransactions() throws Exception {
// given
StoreId storeId = new StoreId(1, 2, 3, 4);
TransactionIdStore transactionIdStore = mock(TransactionIdStore.class);
when(transactionIdStore.getLastCommittedTransactionId()).thenReturn(15L);
LogicalTransactionStore logicalTransactionStore = mock(LogicalTransactionStore.class);
when(logicalTransactionStore.getTransactions(14L)).thenReturn(txCursor(cursor(tx(14), tx(15), tx(16), tx(17))));
TxPullRequestHandler txPullRequestHandler = new TxPullRequestHandler(new CatchupServerProtocol(), () -> storeId, () -> true, () -> transactionIdStore, () -> logicalTransactionStore, BATCH_SIZE, new Monitors(), NullLogProvider.getInstance());
// when
txPullRequestHandler.channelRead0(context, new TxPullRequest(13, storeId));
// then
verify(context, times(3)).write(ResponseMessageType.TX);
verify(context).write(new TxPullResponse(storeId, tx(14)));
verify(context).write(new TxPullResponse(storeId, tx(15)));
verify(context).write(new TxPullResponse(storeId, tx(16)));
verify(context).write(ResponseMessageType.TX_STREAM_FINISHED);
verify(context).write(new TxStreamFinishedResponse(SUCCESS_END_OF_BATCH, 15L));
}
use of org.neo4j.kernel.impl.transaction.log.LogicalTransactionStore in project neo4j by neo4j.
the class RecoveryTest method shouldRecoverExistingData.
@Test
public void shouldRecoverExistingData() throws Exception {
final PhysicalLogFiles logFiles = new PhysicalLogFiles(directory.directory(), "log", fileSystemRule.get());
File file = logFiles.getLogFileForVersion(logVersion);
writeSomeData(file, new Visitor<Pair<LogEntryWriter, Consumer<LogPositionMarker>>, IOException>() {
@Override
public boolean visit(Pair<LogEntryWriter, Consumer<LogPositionMarker>> pair) throws IOException {
LogEntryWriter writer = pair.first();
Consumer<LogPositionMarker> consumer = pair.other();
LogPositionMarker marker = new LogPositionMarker();
// last committed tx
consumer.accept(marker);
LogPosition lastCommittedTxPosition = marker.newPosition();
writer.writeStartEntry(0, 1, 2L, 3L, new byte[0]);
lastCommittedTxStartEntry = new LogEntryStart(0, 1, 2L, 3L, new byte[0], lastCommittedTxPosition);
writer.writeCommitEntry(4L, 5L);
lastCommittedTxCommitEntry = new OnePhaseCommit(4L, 5L);
// check point pointing to the previously committed transaction
writer.writeCheckPointEntry(lastCommittedTxPosition);
expectedCheckPointEntry = new CheckPoint(lastCommittedTxPosition);
// tx committed after checkpoint
consumer.accept(marker);
writer.writeStartEntry(0, 1, 6L, 4L, new byte[0]);
expectedStartEntry = new LogEntryStart(0, 1, 6L, 4L, new byte[0], marker.newPosition());
writer.writeCommitEntry(5L, 7L);
expectedCommitEntry = new OnePhaseCommit(5L, 7L);
return true;
}
});
LifeSupport life = new LifeSupport();
Recovery.Monitor monitor = mock(Recovery.Monitor.class);
final AtomicBoolean recoveryRequired = new AtomicBoolean();
try {
StorageEngine storageEngine = mock(StorageEngine.class);
final LogEntryReader<ReadableClosablePositionAwareChannel> reader = new VersionAwareLogEntryReader<>();
LatestCheckPointFinder finder = new LatestCheckPointFinder(logFiles, fileSystemRule.get(), reader);
LogHeaderCache logHeaderCache = new LogHeaderCache(10);
TransactionMetadataCache metadataCache = new TransactionMetadataCache(100);
LogFile logFile = life.add(new PhysicalLogFile(fileSystemRule.get(), logFiles, 50, () -> transactionIdStore.getLastCommittedTransactionId(), logVersionRepository, mock(PhysicalLogFile.Monitor.class), logHeaderCache));
LogicalTransactionStore txStore = new PhysicalLogicalTransactionStore(logFile, metadataCache, reader);
life.add(new Recovery(new DefaultRecoverySPI(storageEngine, logFiles, fileSystemRule.get(), logVersionRepository, finder, transactionIdStore, txStore, NO_MONITOR) {
private int nr = 0;
@Override
public Visitor<CommittedTransactionRepresentation, Exception> startRecovery() {
recoveryRequired.set(true);
final Visitor<CommittedTransactionRepresentation, Exception> actual = super.startRecovery();
return new Visitor<CommittedTransactionRepresentation, Exception>() {
@Override
public boolean visit(CommittedTransactionRepresentation tx) throws Exception {
actual.visit(tx);
switch(nr++) {
case 0:
assertEquals(lastCommittedTxStartEntry, tx.getStartEntry());
assertEquals(lastCommittedTxCommitEntry, tx.getCommitEntry());
break;
case 1:
assertEquals(expectedStartEntry, tx.getStartEntry());
assertEquals(expectedCommitEntry, tx.getCommitEntry());
break;
default:
fail("Too many recovered transactions");
}
return false;
}
};
}
}, monitor));
life.start();
InOrder order = inOrder(monitor);
order.verify(monitor, times(1)).recoveryRequired(any(LogPosition.class));
order.verify(monitor, times(1)).recoveryCompleted(2);
assertTrue(recoveryRequired.get());
} finally {
life.shutdown();
}
}
use of org.neo4j.kernel.impl.transaction.log.LogicalTransactionStore in project neo4j by neo4j.
the class ResponsePackerIT method shouldPackTheHighestTxCommittedAsObligation.
@Test
public void shouldPackTheHighestTxCommittedAsObligation() throws Exception {
// GIVEN
LogicalTransactionStore transactionStore = mock(LogicalTransactionStore.class);
FileSystemAbstraction fs = fsRule.get();
PageCache pageCache = pageCacheRule.getPageCache(fs);
try (NeoStores neoStore = createNeoStore(fs, pageCache)) {
MetaDataStore store = neoStore.getMetaDataStore();
store.transactionCommitted(2, 111, BASE_TX_COMMIT_TIMESTAMP);
store.transactionCommitted(3, 222, BASE_TX_COMMIT_TIMESTAMP);
store.transactionCommitted(4, 333, BASE_TX_COMMIT_TIMESTAMP);
store.transactionCommitted(5, 444, BASE_TX_COMMIT_TIMESTAMP);
store.transactionCommitted(6, 555, BASE_TX_COMMIT_TIMESTAMP);
// skip 7 to emulate the fact we have an hole in the committed tx ids list
final long expectedTxId = 8L;
store.transactionCommitted(expectedTxId, 777, BASE_TX_COMMIT_TIMESTAMP);
ResponsePacker packer = new ResponsePacker(transactionStore, store, Suppliers.singleton(newStoreIdForCurrentVersion()));
// WHEN
Response<Object> response = packer.packTransactionObligationResponse(new RequestContext(0, 0, 0, 0, 0), new Object());
// THEN
assertTrue(response instanceof TransactionObligationResponse);
((TransactionObligationResponse) response).accept(new Response.Handler() {
@Override
public void obligation(long txId) throws IOException {
assertEquals(expectedTxId, txId);
}
@Override
public Visitor<CommittedTransactionRepresentation, Exception> transactions() {
throw new UnsupportedOperationException("not expected");
}
});
}
}
use of org.neo4j.kernel.impl.transaction.log.LogicalTransactionStore in project neo4j by neo4j.
the class ResponsePackerTest method shouldHaveFixedTargetTransactionIdEvenIfLastTransactionIdIsMoving.
@Test
public void shouldHaveFixedTargetTransactionIdEvenIfLastTransactionIdIsMoving() throws Exception {
// GIVEN
LogicalTransactionStore transactionStore = mock(LogicalTransactionStore.class);
long lastAppliedTransactionId = 5L;
TransactionCursor endlessCursor = new EndlessCursor(lastAppliedTransactionId + 1);
when(transactionStore.getTransactions(anyLong())).thenReturn(endlessCursor);
final long targetTransactionId = 8L;
final TransactionIdStore transactionIdStore = new DeadSimpleTransactionIdStore(targetTransactionId, 0, BASE_TX_COMMIT_TIMESTAMP, 0, 0);
ResponsePacker packer = new ResponsePacker(transactionStore, transactionIdStore, Suppliers.singleton(StoreIdTestFactory.newStoreIdForCurrentVersion()));
// WHEN
Response<Object> response = packer.packTransactionStreamResponse(requestContextStartingAt(5L), null);
final AtomicLong nextExpectedVisit = new AtomicLong(lastAppliedTransactionId);
response.accept(new Response.Handler() {
@Override
public void obligation(long txId) throws IOException {
fail("Should not be called");
}
@Override
public Visitor<CommittedTransactionRepresentation, Exception> transactions() {
return new Visitor<CommittedTransactionRepresentation, Exception>() {
@Override
public boolean visit(CommittedTransactionRepresentation element) {
// THEN
long txId = element.getCommitEntry().getTxId();
assertThat(txId, lessThanOrEqualTo(targetTransactionId));
assertEquals(nextExpectedVisit.incrementAndGet(), txId);
// Move the target transaction id forward one step, effectively always keeping it out of reach
transactionIdStore.setLastCommittedAndClosedTransactionId(transactionIdStore.getLastCommittedTransactionId() + 1, 0, BASE_TX_COMMIT_TIMESTAMP, 3, 4);
return true;
}
};
}
});
}
Aggregations