Search in sources :

Example 1 with CreateConstraintFailureException

use of org.neo4j.kernel.api.exceptions.schema.CreateConstraintFailureException in project neo4j by neo4j.

the class ReplicatedTokenHolder method createCommands.

private byte[] createCommands(String tokenName) {
    StorageEngine storageEngine = dependencies.resolveDependency(StorageEngine.class);
    Collection<StorageCommand> commands = new ArrayList<>();
    TransactionState txState = new TxState();
    int tokenId = Math.toIntExact(idGeneratorFactory.get(tokenIdType).nextId());
    createToken(txState, tokenName, tokenId);
    try (StorageStatement statement = storageEngine.storeReadLayer().newStatement()) {
        storageEngine.createCommands(commands, txState, statement, ResourceLocker.NONE, Long.MAX_VALUE);
    } catch (CreateConstraintFailureException | TransactionFailureException | ConstraintValidationException e) {
        throw new RuntimeException("Unable to create token '" + tokenName + "'", e);
    }
    return ReplicatedTokenRequestSerializer.commandBytes(commands);
}
Also used : TransactionState(org.neo4j.kernel.api.txstate.TransactionState) StorageStatement(org.neo4j.storageengine.api.StorageStatement) StorageCommand(org.neo4j.storageengine.api.StorageCommand) ConstraintValidationException(org.neo4j.kernel.api.exceptions.schema.ConstraintValidationException) ArrayList(java.util.ArrayList) StorageEngine(org.neo4j.storageengine.api.StorageEngine) TransactionFailureException(org.neo4j.kernel.api.exceptions.TransactionFailureException) TxState(org.neo4j.kernel.impl.api.state.TxState) CreateConstraintFailureException(org.neo4j.kernel.api.exceptions.schema.CreateConstraintFailureException)

Example 2 with CreateConstraintFailureException

use of org.neo4j.kernel.api.exceptions.schema.CreateConstraintFailureException 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);
        }
    }
}
Also used : ConstraintViolationTransactionFailureException(org.neo4j.kernel.api.exceptions.ConstraintViolationTransactionFailureException) KeyReadTokenNameLookup(org.neo4j.kernel.api.KeyReadTokenNameLookup) StorageCommand(org.neo4j.storageengine.api.StorageCommand) ConstraintValidationException(org.neo4j.kernel.api.exceptions.schema.ConstraintValidationException) ArrayList(java.util.ArrayList) Locks(org.neo4j.kernel.impl.locking.Locks) StatementLocks(org.neo4j.kernel.impl.locking.StatementLocks) TransactionHookException(org.neo4j.kernel.api.exceptions.TransactionHookException) TransactionFailureException(org.neo4j.kernel.api.exceptions.TransactionFailureException) ConstraintViolationTransactionFailureException(org.neo4j.kernel.api.exceptions.ConstraintViolationTransactionFailureException) CommitEvent(org.neo4j.kernel.impl.transaction.tracing.CommitEvent) PhysicalTransactionRepresentation(org.neo4j.kernel.impl.transaction.log.PhysicalTransactionRepresentation) CreateConstraintFailureException(org.neo4j.kernel.api.exceptions.schema.CreateConstraintFailureException)

Example 3 with CreateConstraintFailureException

use of org.neo4j.kernel.api.exceptions.schema.CreateConstraintFailureException in project neo4j by neo4j.

the class StateHandlingStatementOperations method uniquePropertyConstraintCreate.

@Override
public UniquenessConstraintDescriptor uniquePropertyConstraintCreate(KernelStatement state, LabelSchemaDescriptor descriptor) throws CreateConstraintFailureException {
    UniquenessConstraintDescriptor constraint = ConstraintDescriptorFactory.uniqueForSchema(descriptor);
    try {
        if (state.hasTxStateWithChanges() && // ..., DROP, *CREATE*
        state.txState().indexDoUnRemove(constraint.ownedIndexDescriptor())) {
            // creation is undoing a drop
            if (// CREATE, ..., DROP, *CREATE*
            !state.txState().constraintDoUnRemove(constraint)) {
                // ... the drop we are undoing did itself undo a prior create...
                state.txState().constraintDoAdd(constraint, state.txState().indexCreatedForConstraint(constraint));
            }
        } else // *CREATE*
        {
            // create from scratch
            Iterator<ConstraintDescriptor> it = storeLayer.constraintsGetForSchema(descriptor);
            while (it.hasNext()) {
                if (it.next().equals(constraint)) {
                    return constraint;
                }
            }
            long indexId = constraintIndexCreator.createUniquenessConstraintIndex(state, this, descriptor);
            state.txState().constraintDoAdd(constraint, indexId);
        }
        return constraint;
    } catch (UniquePropertyValueValidationException | DropIndexFailureException | TransactionFailureException e) {
        throw new CreateConstraintFailureException(constraint, e);
    }
}
Also used : UniquePropertyValueValidationException(org.neo4j.kernel.api.exceptions.schema.UniquePropertyValueValidationException) TransactionFailureException(org.neo4j.kernel.api.exceptions.TransactionFailureException) ConstraintDescriptor(org.neo4j.kernel.api.schema_new.constaints.ConstraintDescriptor) UniquenessConstraintDescriptor(org.neo4j.kernel.api.schema_new.constaints.UniquenessConstraintDescriptor) NodeExistenceConstraintDescriptor(org.neo4j.kernel.api.schema_new.constaints.NodeExistenceConstraintDescriptor) RelExistenceConstraintDescriptor(org.neo4j.kernel.api.schema_new.constaints.RelExistenceConstraintDescriptor) UniquenessConstraintDescriptor(org.neo4j.kernel.api.schema_new.constaints.UniquenessConstraintDescriptor) DropIndexFailureException(org.neo4j.kernel.api.exceptions.schema.DropIndexFailureException) CreateConstraintFailureException(org.neo4j.kernel.api.exceptions.schema.CreateConstraintFailureException)

Example 4 with CreateConstraintFailureException

use of org.neo4j.kernel.api.exceptions.schema.CreateConstraintFailureException in project neo4j by neo4j.

the class ConstraintIndexCreator method createUniquenessConstraintIndex.

/**
     * You MUST hold a schema write lock before you call this method.
     * However the schema write lock is temporarily released while populating the index backing the constraint.
     * It goes a little like this:
     * <ol>
     * <li>Prerequisite: Getting here means that there's an open schema transaction which has acquired the
     * SCHEMA WRITE lock.</li>
     * <li>Index schema rule which is backing the constraint is created in a nested mini-transaction
     * which doesn't acquire any locking, merely adds tx state and commits so that the index rule is applied
     * to the store, which triggers the index population</li>
     * <li>Release the SCHEMA WRITE lock</li>
     * <li>Await index population to complete</li>
     * <li>Acquire the SCHEMA WRITE lock (effectively blocking concurrent transactions changing
     * data related to this constraint, and it so happens, most other transactions as well) and verify
     * the uniqueness of the built index</li>
     * <li>Leave this method, knowing that the uniqueness constraint rule will be added to tx state
     * and this tx committed, which will create the uniqueness constraint</li>
     * </ol>
     */
public long createUniquenessConstraintIndex(KernelStatement state, SchemaReadOperations schema, LabelSchemaDescriptor descriptor) throws TransactionFailureException, CreateConstraintFailureException, DropIndexFailureException, UniquePropertyValueValidationException {
    UniquenessConstraintDescriptor constraint = ConstraintDescriptorFactory.uniqueForSchema(descriptor);
    NewIndexDescriptor index = createConstraintIndex(descriptor);
    boolean success = false;
    boolean reacquiredSchemaLock = false;
    Client locks = state.locks().pessimistic();
    try {
        long indexId = schema.indexGetCommittedId(state, index);
        // Release the SCHEMA WRITE lock during index population.
        // At this point the integrity of the constraint to be created was checked
        // while holding the lock and the index rule backing the soon-to-be-created constraint
        // has been created. Now it's just the population left, which can take a long time
        releaseSchemaLock(locks);
        awaitConstrainIndexPopulation(constraint, indexId);
        // Index population was successful, but at this point we don't know if the uniqueness constraint holds.
        // Acquire SCHEMA WRITE lock and verify the constraints here in this user transaction
        // and if everything checks out then it will be held until after the constraint has been
        // created and activated.
        acquireSchemaLock(state, locks);
        reacquiredSchemaLock = true;
        indexingService.getIndexProxy(indexId).verifyDeferredConstraints(propertyAccessor);
        success = true;
        return indexId;
    } catch (SchemaRuleNotFoundException | IndexNotFoundKernelException e) {
        throw new IllegalStateException(String.format("Index (%s) that we just created does not exist.", descriptor));
    } catch (IndexEntryConflictException e) {
        throw new UniquePropertyValueValidationException(constraint, VERIFICATION, e);
    } catch (InterruptedException | IOException e) {
        throw new CreateConstraintFailureException(constraint, e);
    } finally {
        if (!success) {
            if (!reacquiredSchemaLock) {
                acquireSchemaLock(state, locks);
            }
            dropUniquenessConstraintIndex(index);
        }
    }
}
Also used : UniquePropertyValueValidationException(org.neo4j.kernel.api.exceptions.schema.UniquePropertyValueValidationException) SchemaRuleNotFoundException(org.neo4j.kernel.api.exceptions.schema.SchemaRuleNotFoundException) IndexNotFoundKernelException(org.neo4j.kernel.api.exceptions.index.IndexNotFoundKernelException) IOException(java.io.IOException) NewIndexDescriptor(org.neo4j.kernel.api.schema_new.index.NewIndexDescriptor) UniquenessConstraintDescriptor(org.neo4j.kernel.api.schema_new.constaints.UniquenessConstraintDescriptor) Client(org.neo4j.kernel.impl.locking.Locks.Client) IndexEntryConflictException(org.neo4j.kernel.api.exceptions.index.IndexEntryConflictException) CreateConstraintFailureException(org.neo4j.kernel.api.exceptions.schema.CreateConstraintFailureException)

Example 5 with CreateConstraintFailureException

use of org.neo4j.kernel.api.exceptions.schema.CreateConstraintFailureException in project neo4j by neo4j.

the class UniquenessConstraintCreationIT method shouldAbortConstraintCreationWhenDuplicatesExist.

@Test
public void shouldAbortConstraintCreationWhenDuplicatesExist() throws Exception {
    // given
    Statement statement = statementInNewTransaction(AnonymousContext.writeToken());
    // name is not unique for Foo in the existing data
    int foo = statement.tokenWriteOperations().labelGetOrCreateForName("Foo");
    int name = statement.tokenWriteOperations().propertyKeyGetOrCreateForName("name");
    long node1 = statement.dataWriteOperations().nodeCreate();
    statement.dataWriteOperations().nodeAddLabel(node1, foo);
    statement.dataWriteOperations().nodeSetProperty(node1, Property.stringProperty(name, "foo"));
    long node2 = statement.dataWriteOperations().nodeCreate();
    statement.dataWriteOperations().nodeAddLabel(node2, foo);
    statement.dataWriteOperations().nodeSetProperty(node2, Property.stringProperty(name, "foo"));
    commit();
    // when
    LabelSchemaDescriptor descriptor = SchemaDescriptorFactory.forLabel(foo, name);
    try {
        SchemaWriteOperations schemaWriteOperations = schemaWriteOperationsInNewTransaction();
        schemaWriteOperations.uniquePropertyConstraintCreate(descriptor);
        fail("expected exception");
    }// then
     catch (CreateConstraintFailureException ex) {
        assertEquals(ConstraintDescriptorFactory.uniqueForSchema(descriptor), ex.constraint());
        Throwable cause = ex.getCause();
        assertThat(cause, instanceOf(ConstraintValidationException.class));
        String expectedMessage = String.format("Both Node(%d) and Node(%d) have the label `Foo` and property `name` = 'foo'", node1, node2);
        String actualMessage = userMessage((ConstraintValidationException) cause);
        assertEquals(expectedMessage, actualMessage);
    }
}
Also used : SchemaWriteOperations(org.neo4j.kernel.api.SchemaWriteOperations) Statement(org.neo4j.kernel.api.Statement) ConstraintValidationException(org.neo4j.kernel.api.exceptions.schema.ConstraintValidationException) LabelSchemaDescriptor(org.neo4j.kernel.api.schema_new.LabelSchemaDescriptor) CreateConstraintFailureException(org.neo4j.kernel.api.exceptions.schema.CreateConstraintFailureException) Test(org.junit.Test)

Aggregations

CreateConstraintFailureException (org.neo4j.kernel.api.exceptions.schema.CreateConstraintFailureException)5 TransactionFailureException (org.neo4j.kernel.api.exceptions.TransactionFailureException)3 ConstraintValidationException (org.neo4j.kernel.api.exceptions.schema.ConstraintValidationException)3 ArrayList (java.util.ArrayList)2 UniquePropertyValueValidationException (org.neo4j.kernel.api.exceptions.schema.UniquePropertyValueValidationException)2 UniquenessConstraintDescriptor (org.neo4j.kernel.api.schema_new.constaints.UniquenessConstraintDescriptor)2 StorageCommand (org.neo4j.storageengine.api.StorageCommand)2 IOException (java.io.IOException)1 Test (org.junit.Test)1 KeyReadTokenNameLookup (org.neo4j.kernel.api.KeyReadTokenNameLookup)1 SchemaWriteOperations (org.neo4j.kernel.api.SchemaWriteOperations)1 Statement (org.neo4j.kernel.api.Statement)1 ConstraintViolationTransactionFailureException (org.neo4j.kernel.api.exceptions.ConstraintViolationTransactionFailureException)1 TransactionHookException (org.neo4j.kernel.api.exceptions.TransactionHookException)1 IndexEntryConflictException (org.neo4j.kernel.api.exceptions.index.IndexEntryConflictException)1 IndexNotFoundKernelException (org.neo4j.kernel.api.exceptions.index.IndexNotFoundKernelException)1 DropIndexFailureException (org.neo4j.kernel.api.exceptions.schema.DropIndexFailureException)1 SchemaRuleNotFoundException (org.neo4j.kernel.api.exceptions.schema.SchemaRuleNotFoundException)1 LabelSchemaDescriptor (org.neo4j.kernel.api.schema_new.LabelSchemaDescriptor)1 ConstraintDescriptor (org.neo4j.kernel.api.schema_new.constaints.ConstraintDescriptor)1