use of org.neo4j.kernel.impl.transaction.log.PhysicalTransactionRepresentation in project neo4j by neo4j.
the class LegacyBatchIndexApplierTest method shouldOrderTransactionsMakingLegacyIndexChanges.
@Test
public void shouldOrderTransactionsMakingLegacyIndexChanges() throws Throwable {
// GIVEN
Map<String, Integer> names = MapUtil.genericMap("first", 0, "second", 1);
Map<String, Integer> keys = MapUtil.genericMap("key", 0);
String applierName = "test-applier";
LegacyIndexApplierLookup applierLookup = mock(LegacyIndexApplierLookup.class);
when(applierLookup.newApplier(anyString(), anyBoolean())).thenReturn(mock(TransactionApplier.class));
IndexConfigStore config = newIndexConfigStore(names, applierName);
// WHEN multiple legacy index transactions are running, they should be done in order
SynchronizedArrayIdOrderingQueue queue = new SynchronizedArrayIdOrderingQueue(10);
final AtomicLong lastAppliedTxId = new AtomicLong(-1);
Race race = new Race();
for (long i = 0; i < 100; i++) {
final long txId = i;
race.addContestant(() -> {
try (LegacyBatchIndexApplier applier = new LegacyBatchIndexApplier(config, applierLookup, queue, INTERNAL)) {
TransactionToApply txToApply = new TransactionToApply(new PhysicalTransactionRepresentation(new ArrayList<>()));
FakeCommitment commitment = new FakeCommitment(txId, mock(TransactionIdStore.class));
commitment.setHasLegacyIndexChanges(true);
txToApply.commitment(commitment, txId);
TransactionApplier txApplier = applier.startTx(txToApply);
// Make sure threads are unordered
Thread.sleep(ThreadLocalRandom.current().nextInt(5));
// THEN
assertTrue(lastAppliedTxId.compareAndSet(txId - 1, txId));
// Closing manually instead of using try-with-resources since we have no additional work to do in
// txApplier
txApplier.close();
} catch (Exception e) {
throw new RuntimeException(e);
}
});
queue.offer(txId);
}
race.go();
}
use of org.neo4j.kernel.impl.transaction.log.PhysicalTransactionRepresentation in project neo4j by neo4j.
the class CoreReplicatedContentMarshalTest method shouldMarshalTransactionReference.
@Test
public void shouldMarshalTransactionReference() throws Exception {
ByteBuf buffer = Unpooled.buffer();
PhysicalTransactionRepresentation representation = new PhysicalTransactionRepresentation(Collections.emptyList());
representation.setHeader(new byte[] { 0 }, 1, 1, 1, 1, 1, 1);
ReplicatedContent replicatedTx = ReplicatedTransactionFactory.createImmutableReplicatedTransaction(representation);
assertMarshalingEquality(buffer, replicatedTx);
}
use of org.neo4j.kernel.impl.transaction.log.PhysicalTransactionRepresentation in project neo4j by neo4j.
the class KernelTransactionImplementation method commit.
private long commit() throws TransactionFailureException {
boolean success = false;
long txId = READ_ONLY;
try (CommitEvent commitEvent = transactionEvent.beginCommitEvent()) {
// Trigger transaction "before" hooks.
if (hasDataChanges()) {
try {
hooksState = hooks.beforeCommit(txState, this, storageEngine.storeReadLayer(), storageStatement);
if (hooksState != null && hooksState.failed()) {
TransactionHookException cause = hooksState.failure();
throw new TransactionFailureException(Status.Transaction.TransactionHookFailed, cause, "");
}
} finally {
beforeHookInvoked = true;
}
}
// Convert changes into commands and commit
if (hasChanges()) {
// grab all optimistic locks now, locks can't be deferred any further
statementLocks.prepareForCommit();
// use pessimistic locks for the rest of the commit process, locks can't be deferred any further
Locks.Client commitLocks = statementLocks.pessimistic();
// Gather up commands from the various sources
Collection<StorageCommand> extractedCommands = new ArrayList<>();
storageEngine.createCommands(extractedCommands, txState, storageStatement, commitLocks, lastTransactionIdWhenStarted);
if (hasLegacyIndexChanges()) {
legacyIndexTransactionState.extractCommands(extractedCommands);
}
/* 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);
TransactionHeaderInformation headerInformation = headerInformationFactory.create();
long timeCommitted = clock.millis();
transactionRepresentation.setHeader(headerInformation.getAdditionalHeader(), headerInformation.getMasterId(), headerInformation.getAuthorId(), startTimeMillis, lastTransactionIdWhenStarted, timeCommitted, commitLocks.getLockSessionId());
// Commit the transaction
success = true;
TransactionToApply batch = new TransactionToApply(transactionRepresentation);
txId = transactionId = commitProcess.commit(batch, commitEvent, INTERNAL);
commitTime = timeCommitted;
}
}
success = true;
return txId;
} catch (ConstraintValidationException | CreateConstraintFailureException e) {
throw new ConstraintViolationTransactionFailureException(e.getUserMessage(new KeyReadTokenNameLookup(currentTransactionOperations.keyReadOperations())), e);
} finally {
if (!success) {
rollback();
} else {
afterCommit(txId);
}
}
}
use of org.neo4j.kernel.impl.transaction.log.PhysicalTransactionRepresentation in project neo4j by neo4j.
the class ApplyRecoveredTransactionsTest method applyExternalTransaction.
private void applyExternalTransaction(long transactionId, Command... commands) throws Exception {
LockService lockService = mock(LockService.class);
when(lockService.acquireNodeLock(anyLong(), any(LockService.LockType.class))).thenReturn(LockService.NO_LOCK);
when(lockService.acquireRelationshipLock(anyLong(), any(LockService.LockType.class))).thenReturn(LockService.NO_LOCK);
NeoStoreBatchTransactionApplier applier = new NeoStoreBatchTransactionApplier(neoStores, mock(CacheAccessBackDoor.class), lockService);
TransactionRepresentation tx = new PhysicalTransactionRepresentation(Arrays.asList(commands));
CommandHandlerContract.apply(applier, txApplier -> {
tx.accept(txApplier);
return false;
}, new TransactionToApply(tx, transactionId));
}
use of org.neo4j.kernel.impl.transaction.log.PhysicalTransactionRepresentation in project neo4j by neo4j.
the class TransactionRecordStateTest method movingBilaterallyOfTheDenseNodeThresholdIsConsistent.
@Test
public void movingBilaterallyOfTheDenseNodeThresholdIsConsistent() throws Exception {
// GIVEN
NeoStores neoStores = neoStoresRule.open(GraphDatabaseSettings.dense_node_threshold.name(), "10");
TransactionRecordState tx = newTransactionRecordState(neoStores);
long nodeId = neoStores.getNodeStore().nextId();
tx.nodeCreate(nodeId);
int typeA = (int) neoStores.getRelationshipTypeTokenStore().nextId();
tx.createRelationshipTypeToken("A", typeA);
createRelationships(neoStores, tx, nodeId, typeA, INCOMING, 20);
BatchTransactionApplier applier = new NeoStoreBatchTransactionApplier(neoStores, mock(CacheAccessBackDoor.class), LockService.NO_LOCK_SERVICE);
apply(applier, transaction(tx));
tx = newTransactionRecordState(neoStores);
int typeB = 1;
tx.createRelationshipTypeToken("B", typeB);
// WHEN
// i remove enough relationships to become dense and remove enough to become not dense
long[] relationshipsOfTypeB = createRelationships(neoStores, tx, nodeId, typeB, OUTGOING, 5);
for (long relationshipToDelete : relationshipsOfTypeB) {
tx.relDelete(relationshipToDelete);
}
PhysicalTransactionRepresentation ptx = transactionRepresentationOf(tx);
apply(applier, ptx);
// THEN
// The dynamic label record in before should be the same id as in after, and should be in use
final AtomicBoolean foundRelationshipGroupInUse = new AtomicBoolean();
ptx.accept(command -> ((Command) command).handle(new CommandVisitor.Adapter() {
@Override
public boolean visitRelationshipGroupCommand(Command.RelationshipGroupCommand command) throws IOException {
if (command.getAfter().inUse()) {
if (!foundRelationshipGroupInUse.get()) {
foundRelationshipGroupInUse.set(true);
} else {
fail();
}
}
return false;
}
}));
assertTrue("Did not create relationship group command", foundRelationshipGroupInUse.get());
}
Aggregations