Search in sources :

Example 11 with CommandsToApply

use of org.neo4j.storageengine.api.CommandsToApply in project neo4j by neo4j.

the class RecordStorageEngineTest method panicOnExceptionDuringCommandsApply.

@Test
void panicOnExceptionDuringCommandsApply() {
    IllegalStateException failure = new IllegalStateException("Too many open files");
    RecordStorageEngine engine = storageEngineRule.getWith(fs, pageCache, databaseLayout).databaseHealth(databaseHealth).transactionApplierTransformer(facade -> transactionApplierFacadeTransformer(facade, failure)).build();
    CommandsToApply commandsToApply = mock(CommandsToApply.class);
    var exception = assertThrows(Exception.class, () -> engine.apply(commandsToApply, TransactionApplicationMode.INTERNAL));
    assertSame(failure, getRootCause(exception));
    verify(databaseHealth).panic(any(Throwable.class));
}
Also used : Visitor(org.neo4j.internal.helpers.collection.Visitor) BeforeEach(org.junit.jupiter.api.BeforeEach) StoreFileMetadata(org.neo4j.storageengine.api.StoreFileMetadata) Status(org.neo4j.kernel.api.exceptions.Status) Assertions.assertThat(org.assertj.core.api.Assertions.assertThat) DatabaseLayout(org.neo4j.io.layout.DatabaseLayout) IdUpdateListener(org.neo4j.kernel.impl.store.IdUpdateListener) Mockito.doThrow(org.mockito.Mockito.doThrow) UnderlyingStorageException(org.neo4j.exceptions.UnderlyingStorageException) NULL(org.neo4j.io.pagecache.context.CursorContext.NULL) EXCLUSIVE(org.neo4j.lock.LockType.EXCLUSIVE) Path(java.nio.file.Path) PageCache(org.neo4j.io.pagecache.PageCache) Collection(java.util.Collection) Set(java.util.Set) LockService(org.neo4j.lock.LockService) Collectors(java.util.stream.Collectors) Test(org.junit.jupiter.api.Test) EphemeralNeo4jLayoutExtension(org.neo4j.test.extension.EphemeralNeo4jLayoutExtension) Mockito.inOrder(org.mockito.Mockito.inOrder) CommandsToApply(org.neo4j.storageengine.api.CommandsToApply) Mockito.mock(org.mockito.Mockito.mock) Lock(org.neo4j.lock.Lock) Assertions.assertThrows(org.junit.jupiter.api.Assertions.assertThrows) Assertions.fail(org.junit.jupiter.api.Assertions.fail) ArgumentMatchers.any(org.mockito.ArgumentMatchers.any) Assertions.assertNotNull(org.junit.jupiter.api.Assertions.assertNotNull) ArrayList(java.util.ArrayList) StorageCommand(org.neo4j.storageengine.api.StorageCommand) RecordStorageEngineRule(org.neo4j.test.rule.RecordStorageEngineRule) ArgumentCaptor(org.mockito.ArgumentCaptor) Inject(org.neo4j.test.extension.Inject) ThreadLocalRandom(java.util.concurrent.ThreadLocalRandom) TransactionApplicationMode(org.neo4j.storageengine.api.TransactionApplicationMode) Assertions.assertEquals(org.junit.jupiter.api.Assertions.assertEquals) InOrder(org.mockito.InOrder) ExceptionUtils.getRootCause(org.apache.commons.lang3.exception.ExceptionUtils.getRootCause) IOException(java.io.IOException) Health(org.neo4j.monitoring.Health) Mockito.when(org.mockito.Mockito.when) DatabaseHealth(org.neo4j.monitoring.DatabaseHealth) EphemeralPageCacheExtension(org.neo4j.test.extension.pagecache.EphemeralPageCacheExtension) Assertions.assertSame(org.junit.jupiter.api.Assertions.assertSame) Mockito.verify(org.mockito.Mockito.verify) Consumer(java.util.function.Consumer) AfterEach(org.junit.jupiter.api.AfterEach) KernelException(org.neo4j.exceptions.KernelException) EphemeralFileSystemAbstraction(org.neo4j.io.fs.EphemeralFileSystemAbstraction) NodeRecord(org.neo4j.kernel.impl.store.record.NodeRecord) Timeout(org.junit.jupiter.api.Timeout) CommandsToApply(org.neo4j.storageengine.api.CommandsToApply) Test(org.junit.jupiter.api.Test)

Example 12 with CommandsToApply

use of org.neo4j.storageengine.api.CommandsToApply in project neo4j by neo4j.

the class RecordStorageEngineTest method shouldCloseLockGroupAfterAppliers.

@Test
void shouldCloseLockGroupAfterAppliers() throws Exception {
    // given
    long nodeId = 5;
    LockService lockService = mock(LockService.class);
    Lock nodeLock = mock(Lock.class);
    when(lockService.acquireNodeLock(nodeId, EXCLUSIVE)).thenReturn(nodeLock);
    // <-- simply so that we can use InOrder mockito construct
    Consumer<Boolean> applierCloseCall = mock(Consumer.class);
    CapturingTransactionApplierFactoryChain applier = new CapturingTransactionApplierFactoryChain(applierCloseCall);
    RecordStorageEngine engine = recordStorageEngineBuilder().lockService(lockService).transactionApplierTransformer(applier::wrapAroundActualApplier).build();
    CommandsToApply commandsToApply = mock(CommandsToApply.class);
    when(commandsToApply.cursorContext()).thenReturn(NULL);
    when(commandsToApply.accept(any())).thenAnswer(invocationOnMock -> {
        // Visit one node command
        Visitor<StorageCommand, IOException> visitor = invocationOnMock.getArgument(0);
        NodeRecord after = new NodeRecord(nodeId);
        after.setInUse(true);
        visitor.visit(new Command.NodeCommand(new NodeRecord(nodeId), after));
        return null;
    });
    // when
    engine.apply(commandsToApply, TransactionApplicationMode.INTERNAL);
    // then
    InOrder inOrder = inOrder(lockService, applierCloseCall, nodeLock);
    inOrder.verify(lockService).acquireNodeLock(nodeId, EXCLUSIVE);
    inOrder.verify(applierCloseCall).accept(true);
    inOrder.verify(nodeLock).release();
    inOrder.verifyNoMoreInteractions();
}
Also used : InOrder(org.mockito.InOrder) LockService(org.neo4j.lock.LockService) StorageCommand(org.neo4j.storageengine.api.StorageCommand) IOException(java.io.IOException) Lock(org.neo4j.lock.Lock) CommandsToApply(org.neo4j.storageengine.api.CommandsToApply) NodeRecord(org.neo4j.kernel.impl.store.record.NodeRecord) StorageCommand(org.neo4j.storageengine.api.StorageCommand) Test(org.junit.jupiter.api.Test)

Example 13 with CommandsToApply

use of org.neo4j.storageengine.api.CommandsToApply in project neo4j by neo4j.

the class RecordStorageEngineTest method executeFailingTransaction.

private static Exception executeFailingTransaction(RecordStorageEngine engine) throws IOException {
    Exception applicationError = new UnderlyingStorageException("No space left on device");
    CommandsToApply txToApply = newTransactionThatFailsWith(applicationError);
    try {
        engine.apply(txToApply, TransactionApplicationMode.INTERNAL);
        fail("Exception expected");
    } catch (Exception e) {
        assertSame(applicationError, getRootCause(e));
    }
    return applicationError;
}
Also used : CommandsToApply(org.neo4j.storageengine.api.CommandsToApply) UnderlyingStorageException(org.neo4j.exceptions.UnderlyingStorageException) UnderlyingStorageException(org.neo4j.exceptions.UnderlyingStorageException) IOException(java.io.IOException) KernelException(org.neo4j.exceptions.KernelException)

Example 14 with CommandsToApply

use of org.neo4j.storageengine.api.CommandsToApply in project neo4j by neo4j.

the class TransactionRecordStateTest method shouldWriteProperPropertyRecordsWhenOnlyChangingLinkage.

@Test
void shouldWriteProperPropertyRecordsWhenOnlyChangingLinkage() throws Exception {
    neoStores = createStores();
    /* There was an issue where GIVEN:
         *
         *   Legend: () = node, [] = property record
         *
         *   ()-->[0:block{size:1}]
         *
         * WHEN adding a new property record in front of if, not changing any data in that record i.e:
         *
         *   ()-->[1:block{size:4}]-->[0:block{size:1}]
         *
         * The state of property record 0 would be that it had loaded value records for that block,
         * but those value records weren't heavy, so writing that record to the log would fail
         * w/ an assertion data != null.
         */
    // GIVEN
    TransactionRecordState recordState = newTransactionRecordState();
    int nodeId = 0;
    recordState.nodeCreate(nodeId);
    int index = 0;
    // will require a block of size 1
    recordState.nodeAddProperty(nodeId, index, string(70));
    apply(recordState);
    // WHEN
    recordState = newTransactionRecordState();
    int index2 = 1;
    // will require a block of size 4
    recordState.nodeAddProperty(nodeId, index2, string(40));
    // THEN
    CommandsToApply representation = transaction(recordState);
    representation.accept(command -> ((Command) command).handle(new CommandVisitor.Adapter() {

        @Override
        public boolean visitPropertyCommand(PropertyCommand command) {
            // THEN
            verifyPropertyRecord(command.getBefore());
            verifyPropertyRecord(command.getAfter());
            return false;
        }

        private void verifyPropertyRecord(PropertyRecord record) {
            if (record.getPrevProp() != Record.NO_NEXT_PROPERTY.intValue()) {
                for (PropertyBlock block : record) {
                    assertTrue(block.isLight());
                }
            }
        }
    }));
}
Also used : CommandsToApply(org.neo4j.storageengine.api.CommandsToApply) PropertyRecord(org.neo4j.kernel.impl.store.record.PropertyRecord) PropertyBlock(org.neo4j.kernel.impl.store.record.PropertyBlock) PropertyCommand(org.neo4j.internal.recordstorage.Command.PropertyCommand) Test(org.junit.jupiter.api.Test)

Example 15 with CommandsToApply

use of org.neo4j.storageengine.api.CommandsToApply in project neo4j by neo4j.

the class TransactionRecordStateTest method shouldDeleteDynamicLabelsForDeletedNodeForRecoveredTransaction.

@Test
void shouldDeleteDynamicLabelsForDeletedNodeForRecoveredTransaction() throws Throwable {
    neoStores = createStores();
    // GIVEN a store that has got a node with a dynamic label record
    TransactionApplierFactory applier = buildApplier(LockService.NO_LOCK_SERVICE);
    AtomicLong nodeId = new AtomicLong();
    AtomicLong dynamicLabelRecordId = new AtomicLong();
    apply(applier, transaction(nodeWithDynamicLabelRecord(neoStores, nodeId, dynamicLabelRecordId)));
    assertDynamicLabelRecordInUse(neoStores, dynamicLabelRecordId.get(), true);
    // WHEN applying a transaction, which has first round-tripped through a log (written then read)
    CommandsToApply transaction = transaction(deleteNode(nodeId.get()));
    InMemoryVersionableReadableClosablePositionAwareChannel channel = new InMemoryVersionableReadableClosablePositionAwareChannel();
    writeToChannel(transaction, channel);
    CommandsToApply recoveredTransaction = readFromChannel(channel);
    // and applying that recovered transaction
    apply(applier, recoveredTransaction);
    // THEN should have the dynamic label record should be deleted as well
    assertDynamicLabelRecordInUse(neoStores, dynamicLabelRecordId.get(), false);
}
Also used : CommandsToApply(org.neo4j.storageengine.api.CommandsToApply) AtomicLong(java.util.concurrent.atomic.AtomicLong) InMemoryVersionableReadableClosablePositionAwareChannel(org.neo4j.kernel.impl.transaction.log.InMemoryVersionableReadableClosablePositionAwareChannel) Test(org.junit.jupiter.api.Test)

Aggregations

CommandsToApply (org.neo4j.storageengine.api.CommandsToApply)15 Test (org.junit.jupiter.api.Test)8 IOException (java.io.IOException)4 InOrder (org.mockito.InOrder)3 StorageCommand (org.neo4j.storageengine.api.StorageCommand)3 ArrayList (java.util.ArrayList)2 Collection (java.util.Collection)2 ThreadLocalRandom (java.util.concurrent.ThreadLocalRandom)2 Mockito.doThrow (org.mockito.Mockito.doThrow)2 Mockito.mock (org.mockito.Mockito.mock)2 Mockito.verify (org.mockito.Mockito.verify)2 Mockito.when (org.mockito.Mockito.when)2 KernelException (org.neo4j.exceptions.KernelException)2 UnderlyingStorageException (org.neo4j.exceptions.UnderlyingStorageException)2 NodeRecord (org.neo4j.kernel.impl.store.record.NodeRecord)2 Lock (org.neo4j.lock.Lock)2 LockService (org.neo4j.lock.LockService)2 File (java.io.File)1 Path (java.nio.file.Path)1 EnumMap (java.util.EnumMap)1