use of org.neo4j.storageengine.api.StorageCommand in project neo4j by neo4j.
the class LogTruncationTest method assertHandlesLogTruncation.
private void assertHandlesLogTruncation(Command cmd) throws IOException {
inMemoryChannel.reset();
writer.serialize(new PhysicalTransactionRepresentation(Arrays.asList(cmd)));
int bytesSuccessfullyWritten = inMemoryChannel.writerPosition();
try {
LogEntry logEntry = logEntryReader.readLogEntry(inMemoryChannel);
StorageCommand command = ((LogEntryCommand) logEntry).getXaCommand();
assertEquals(cmd, command);
} catch (Exception e) {
throw new AssertionError("Failed to deserialize " + cmd.toString() + ", because: ", e);
}
bytesSuccessfullyWritten--;
while (bytesSuccessfullyWritten-- > 0) {
inMemoryChannel.reset();
writer.serialize(new PhysicalTransactionRepresentation(Arrays.asList(cmd)));
inMemoryChannel.truncateTo(bytesSuccessfullyWritten);
LogEntry deserialized = logEntryReader.readLogEntry(inMemoryChannel);
assertNull("Deserialization did not detect log truncation!" + "Record: " + cmd + ", deserialized: " + deserialized, deserialized);
}
}
use of org.neo4j.storageengine.api.StorageCommand in project neo4j by neo4j.
the class MadeUpServerImplementation method transaction.
private TransactionRepresentation transaction(long txId) {
Collection<StorageCommand> commands = new ArrayList<>();
NodeRecord node = new NodeRecord(txId);
node.setInUse(true);
commands.add(new NodeCommand(new NodeRecord(txId), node));
PhysicalTransactionRepresentation transaction = new PhysicalTransactionRepresentation(commands);
transaction.setHeader(new byte[0], 0, 0, 0, 0, 0, 0);
return transaction;
}
use of org.neo4j.storageengine.api.StorageCommand in project neo4j by neo4j.
the class LabelAndIndexUpdateBatchingIT method findCutoffIndex.
private static int findCutoffIndex(Collection<TransactionRepresentation> transactions) throws IOException {
Iterator<TransactionRepresentation> iterator = transactions.iterator();
for (int i = 0; iterator.hasNext(); i++) {
TransactionRepresentation tx = iterator.next();
CommandExtractor extractor = new CommandExtractor();
tx.accept(extractor);
List<StorageCommand> nodeCommands = extractor.commands.stream().filter(command -> command instanceof NodeCommand).collect(toList());
if (nodeCommands.size() == 1) {
return i;
}
}
throw new AssertionError("Couldn't find the transaction which would be the cut-off point");
}
use of org.neo4j.storageengine.api.StorageCommand in project neo4j by neo4j.
the class PhysicalTransactionCursor method next.
@Override
public boolean next() throws IOException {
// Clear the previous deserialized transaction so that it won't have to be kept in heap while deserializing
// the next one. Could be problematic if both are really big.
current = null;
while (true) {
if (!logEntryCursor.next()) {
return false;
}
LogEntry entry = logEntryCursor.get();
if (entry instanceof LogEntryInlinedCheckPoint) {
// this is a good position anyhow
channel.getCurrentPosition(lastGoodPositionMarker);
continue;
}
assert entry instanceof LogEntryStart : "Expected Start entry, read " + entry + " instead";
LogEntryStart startEntry = (LogEntryStart) entry;
LogEntryCommit commitEntry;
List<StorageCommand> entries = new ArrayList<>();
while (true) {
if (!logEntryCursor.next()) {
return false;
}
entry = logEntryCursor.get();
if (entry instanceof LogEntryCommit) {
commitEntry = (LogEntryCommit) entry;
break;
}
LogEntryCommand command = (LogEntryCommand) entry;
entries.add(command.getCommand());
}
PhysicalTransactionRepresentation transaction = new PhysicalTransactionRepresentation(entries);
transaction.setHeader(startEntry.getAdditionalHeader(), startEntry.getTimeWritten(), startEntry.getLastCommittedTxWhenTransactionStarted(), commitEntry.getTimeWritten(), -1, ANONYMOUS);
current = new CommittedTransactionRepresentation(startEntry, transaction, commitEntry);
channel.getCurrentPosition(lastGoodPositionMarker);
return true;
}
}
use of org.neo4j.storageengine.api.StorageCommand in project neo4j by neo4j.
the class KernelTransactionImplementation method commitTransaction.
private long commitTransaction() throws KernelException {
boolean success = false;
long txId = READ_ONLY_ID;
TransactionListenersState listenersState = null;
try (CommitEvent commitEvent = transactionEvent.beginCommitEvent()) {
listenersState = eventListeners.beforeCommit(txState, this, storageReader);
if (listenersState != null && listenersState.isFailed()) {
Throwable cause = listenersState.failure();
if (cause instanceof TransientFailureException) {
throw (TransientFailureException) cause;
}
if (cause instanceof Status.HasStatus) {
throw new TransactionFailureException(((Status.HasStatus) cause).status(), cause, cause.getMessage());
}
throw new TransactionFailureException(Status.Transaction.TransactionHookFailed, cause, cause.getMessage());
}
// Convert changes into commands and commit
if (hasChanges()) {
forceThawLocks();
lockClient.prepareForCommit();
// Gather up commands from the various sources
HeapTrackingArrayList<StorageCommand> extractedCommands = HeapTrackingCollections.newArrayList(memoryTracker);
storageEngine.createCommands(extractedCommands, txState, storageReader, commandCreationContext, lockClient, lockTracer(), lastTransactionIdWhenStarted, this::enforceConstraints, cursorContext, memoryTracker);
/* Here's the deal: we track a quick-to-access hasChanges in transaction state which is true
* if there are any changes imposed by this transaction. Some changes made inside a transaction undo
* previously made changes in that same transaction, and so at some point a transaction may have
* changes and at another point, after more changes seemingly,
* the transaction may not have any changes.
* However, to track that "undoing" of the changes is a bit tedious, intrusive and hard to maintain
* and get right.... So to really make sure the transaction has changes we re-check by looking if we
* have produced any commands to add to the logical log.
*/
if (!extractedCommands.isEmpty()) {
// Finish up the whole transaction representation
PhysicalTransactionRepresentation transactionRepresentation = new PhysicalTransactionRepresentation(extractedCommands);
long timeCommitted = clocks.systemClock().millis();
transactionRepresentation.setHeader(EMPTY_BYTE_ARRAY, startTimeMillis, lastTransactionIdWhenStarted, timeCommitted, leaseClient.leaseId(), securityContext.subject());
// Commit the transaction
success = true;
TransactionToApply batch = new TransactionToApply(transactionRepresentation, cursorContext);
kernelTransactionMonitor.beforeApply();
txId = commitProcess.commit(batch, commitEvent, INTERNAL);
commitTime = timeCommitted;
}
}
success = true;
return txId;
} catch (ConstraintValidationException | CreateConstraintFailureException e) {
throw new ConstraintViolationTransactionFailureException(e.getUserMessage(tokenRead()), e);
} finally {
if (!success) {
rollback(listenersState);
} else {
transactionId = txId;
afterCommit(listenersState);
}
transactionMonitor.addHeapTransactionSize(memoryTracker.heapHighWaterMark());
transactionMonitor.addNativeTransactionSize(memoryTracker.usedNativeMemory());
}
}
Aggregations