use of org.neo4j.causalclustering.catchup.CatchupResult in project neo4j by neo4j.
the class CoreStateDownloader method downloadSnapshot.
public synchronized void downloadSnapshot(MemberId source, CoreState coreState) throws StoreCopyFailedException {
try {
/* Extract some key properties before shutting it down. */
boolean isEmptyStore = localDatabase.isEmpty();
if (!isEmptyStore) {
/* make sure it's recovered before we start messing with catchup */
localDatabase.start();
localDatabase.stop();
}
StoreId remoteStoreId = remoteStore.getStoreId(source);
if (!isEmptyStore && !remoteStoreId.equals(localDatabase.storeId())) {
throw new StoreCopyFailedException("StoreId mismatch and not empty");
}
startStopOnStoreCopy.stop();
localDatabase.stopForStoreCopy();
log.info("Downloading snapshot from core server at %s", source);
/* The core snapshot must be copied before the store, because the store has a dependency on
* the state of the state machines. The store will thus be at or ahead of the state machines,
* in consensus log index, and application of commands will bring them in sync. Any such commands
* that carry transactions will thus be ignored by the transaction/token state machines, since they
* are ahead, and the correct decisions for their applicability have already been taken as encapsulated
* in the copied store. */
CoreSnapshot coreSnapshot = catchUpClient.makeBlockingRequest(source, new CoreSnapshotRequest(), new CatchUpResponseAdaptor<CoreSnapshot>() {
@Override
public void onCoreSnapshot(CompletableFuture<CoreSnapshot> signal, CoreSnapshot response) {
signal.complete(response);
}
});
if (isEmptyStore) {
storeCopyProcess.replaceWithStoreFrom(source, remoteStoreId);
} else {
StoreId localStoreId = localDatabase.storeId();
CatchupResult catchupResult = remoteStore.tryCatchingUp(source, localStoreId, localDatabase.storeDir());
if (catchupResult == E_TRANSACTION_PRUNED) {
log.info("Failed to pull transactions from " + source + ". They may have been pruned away.");
localDatabase.delete();
storeCopyProcess.replaceWithStoreFrom(source, localStoreId);
} else if (catchupResult != SUCCESS_END_OF_STREAM) {
throw new StoreCopyFailedException("Failed to download store: " + catchupResult);
}
}
/* We install the snapshot after the store has been downloaded,
* so that we are not left with a state ahead of the store. */
coreState.installSnapshot(coreSnapshot);
log.info("Core snapshot installed: " + coreSnapshot);
/* Starting the database will invoke the commit process factory in
* the EnterpriseCoreEditionModule, which has important side-effects. */
log.info("Starting local database");
localDatabase.start();
coreStateMachines.installCommitProcess(localDatabase.getCommitProcess());
startStopOnStoreCopy.start();
} catch (StoreCopyFailedException e) {
throw e;
} catch (Throwable e) {
throw new StoreCopyFailedException(e);
}
}
use of org.neo4j.causalclustering.catchup.CatchupResult in project neo4j by neo4j.
the class TxStreamFinishedResponseDecoder method decode.
@Override
protected void decode(ChannelHandlerContext ctx, ByteBuf msg, List<Object> out) throws Exception {
int ordinal = msg.readInt();
long latestTxid = msg.readLong();
CatchupResult status = CatchupResult.values()[ordinal];
out.add(new TxStreamFinishedResponse(status, latestTxid));
}
use of org.neo4j.causalclustering.catchup.CatchupResult in project neo4j by neo4j.
the class RemoteStore method pullTransactions.
private CatchupResult pullTransactions(MemberId from, StoreId expectedStoreId, File storeDir, long fromTxId, boolean asPartOfStoreCopy) throws IOException, StoreCopyFailedException {
try (TransactionLogCatchUpWriter writer = transactionLogFactory.create(storeDir, fs, pageCache, logProvider, fromTxId, asPartOfStoreCopy)) {
log.info("Pulling transactions from: %d", fromTxId);
long previousTxId = fromTxId - 1;
CatchupResult lastStatus;
do {
TxPullRequestResult result = txPullClient.pullTransactions(from, expectedStoreId, previousTxId, writer);
lastStatus = result.catchupResult();
previousTxId = result.lastTxId();
} while (lastStatus == SUCCESS_END_OF_BATCH);
return lastStatus;
} catch (CatchUpClientException e) {
throw new StoreCopyFailedException(e);
}
}
use of org.neo4j.causalclustering.catchup.CatchupResult in project neo4j by neo4j.
the class RemoteStore method copy.
public void copy(MemberId from, StoreId expectedStoreId, File destDir) throws StoreCopyFailedException, StreamingTransactionsFailedException {
try {
log.info("Copying store from %s", from);
long lastFlushedTxId;
try (StreamToDisk storeFileStreams = new StreamToDisk(destDir, fs, pageCache, monitors)) {
lastFlushedTxId = storeCopyClient.copyStoreFiles(from, expectedStoreId, storeFileStreams);
}
log.info("Store files need to be recovered starting from: %d", lastFlushedTxId);
CatchupResult catchupResult = pullTransactions(from, expectedStoreId, destDir, lastFlushedTxId, true);
if (catchupResult != SUCCESS_END_OF_STREAM) {
throw new StreamingTransactionsFailedException("Failed to pull transactions: " + catchupResult);
}
} catch (IOException e) {
throw new StoreCopyFailedException(e);
}
}
use of org.neo4j.causalclustering.catchup.CatchupResult in project neo4j by neo4j.
the class TxPullRequestHandler method channelRead0.
@Override
protected void channelRead0(ChannelHandlerContext ctx, final TxPullRequest msg) throws Exception {
long firstTxId = Math.max(msg.previousTxId(), BASE_TX_ID) + 1;
long lastTxId = firstTxId;
CatchupResult status = SUCCESS_END_OF_STREAM;
StoreId localStoreId = storeIdSupplier.get();
long lastCommittedTransactionId = transactionIdStore.getLastCommittedTransactionId();
if (localStoreId == null || !localStoreId.equals(msg.expectedStoreId())) {
status = E_STORE_ID_MISMATCH;
log.info("Failed to serve TxPullRequest for tx %d and storeId %s because that storeId is different " + "from this machine with %s", lastTxId, msg.expectedStoreId(), localStoreId);
} else if (!databaseAvailable.getAsBoolean()) {
// database is not available for pulling transactions...
status = E_STORE_UNAVAILABLE;
log.info("Failed to serve TxPullRequest for tx %d because the local database is unavailable.", lastTxId);
} else if (lastCommittedTransactionId >= firstTxId) {
try (IOCursor<CommittedTransactionRepresentation> cursor = logicalTransactionStore.getTransactions(firstTxId)) {
status = SUCCESS_END_OF_BATCH;
for (int i = 0; i < batchSize; i++) {
if (cursor.next()) {
ctx.write(ResponseMessageType.TX);
CommittedTransactionRepresentation tx = cursor.get();
lastTxId = tx.getCommitEntry().getTxId();
ctx.write(new TxPullResponse(localStoreId, tx));
} else {
status = SUCCESS_END_OF_STREAM;
break;
}
}
ctx.flush();
} catch (NoSuchTransactionException e) {
status = E_TRANSACTION_PRUNED;
log.info("Failed to serve TxPullRequest for tx %d because the transaction does not exist.", lastTxId);
}
}
ctx.write(ResponseMessageType.TX_STREAM_FINISHED);
TxStreamFinishedResponse response = new TxStreamFinishedResponse(status, lastCommittedTransactionId);
ctx.write(response);
ctx.flush();
monitor.increment();
protocol.expect(State.MESSAGE_TYPE);
}
Aggregations