Search in sources :

Example 1 with TransactionFailureException

use of org.neo4j.internal.kernel.api.exceptions.TransactionFailureException in project neo4j by neo4j.

the class IntegrityValidator method validateSchemaRule.

void validateSchemaRule(SchemaRule schemaRule) throws TransactionFailureException {
    Preconditions.checkState(indexValidator != null, "No index validator installed");
    KernelVersion currentVersion = neoStores.getMetaDataStore().kernelVersion();
    if (currentVersion.isLessThan(VERSION_IN_WHICH_TOKEN_INDEXES_ARE_INTRODUCED)) {
        if (schemaRule instanceof IndexDescriptor) {
            IndexDescriptor index = (IndexDescriptor) schemaRule;
            if (index.isTokenIndex() || isBtreeRelationshipPropertyIndex(index)) {
                throw new TransactionFailureException(Status.General.UpgradeRequired, "Index operation on index '%s' not allowed. " + "Required kernel version for this transaction is %s, but actual version was %s.", index, VERSION_IN_WHICH_TOKEN_INDEXES_ARE_INTRODUCED.name(), currentVersion.name());
            }
        }
    }
    if (schemaRule instanceof ConstraintDescriptor) {
        ConstraintDescriptor constraint = (ConstraintDescriptor) schemaRule;
        if (constraint.isIndexBackedConstraint()) {
            long ownedIndex = constraint.asIndexBackedConstraint().ownedIndexId();
            try {
                indexValidator.validateIndex(ownedIndex);
            } catch (KernelException e) {
                // and have recovery performed. It's the safest bet to avoid loosing data.
                throw new TransactionFailureException(Status.Transaction.TransactionValidationFailed, e, "Index validation of " + schemaRule + " failed, specifically for its owned index " + ownedIndex, e);
            }
        }
    }
}
Also used : KernelVersion(org.neo4j.kernel.KernelVersion) ConstraintViolationTransactionFailureException(org.neo4j.internal.kernel.api.exceptions.ConstraintViolationTransactionFailureException) TransactionFailureException(org.neo4j.internal.kernel.api.exceptions.TransactionFailureException) ConstraintDescriptor(org.neo4j.internal.schema.ConstraintDescriptor) IndexDescriptor(org.neo4j.internal.schema.IndexDescriptor) KernelException(org.neo4j.exceptions.KernelException)

Example 2 with TransactionFailureException

use of org.neo4j.internal.kernel.api.exceptions.TransactionFailureException 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());
    }
}
Also used : Status(org.neo4j.kernel.api.exceptions.Status) ConstraintViolationTransactionFailureException(org.neo4j.internal.kernel.api.exceptions.ConstraintViolationTransactionFailureException) TransientFailureException(org.neo4j.graphdb.TransientFailureException) StorageCommand(org.neo4j.storageengine.api.StorageCommand) ConstraintValidationException(org.neo4j.internal.kernel.api.exceptions.schema.ConstraintValidationException) TransactionFailureException(org.neo4j.internal.kernel.api.exceptions.TransactionFailureException) ConstraintViolationTransactionFailureException(org.neo4j.internal.kernel.api.exceptions.ConstraintViolationTransactionFailureException) CommitEvent(org.neo4j.kernel.impl.transaction.tracing.CommitEvent) TransactionListenersState(org.neo4j.kernel.internal.event.TransactionListenersState) PhysicalTransactionRepresentation(org.neo4j.kernel.impl.transaction.log.PhysicalTransactionRepresentation) CreateConstraintFailureException(org.neo4j.internal.kernel.api.exceptions.schema.CreateConstraintFailureException)

Example 3 with TransactionFailureException

use of org.neo4j.internal.kernel.api.exceptions.TransactionFailureException in project neo4j by neo4j.

the class KernelTransactionImplementation method closeTransaction.

@Override
public long closeTransaction() throws TransactionFailureException {
    assertTransactionOpen();
    assertTransactionNotClosing();
    closing = true;
    try {
        if (failure || !success || isTerminated()) {
            rollback(null);
            failOnNonExplicitRollbackIfNeeded();
            return ROLLBACK_ID;
        } else {
            return commitTransaction();
        }
    } catch (TransactionFailureException e) {
        throw e;
    } catch (KernelException e) {
        throw new TransactionFailureException(e.status(), e, "Unexpected kernel exception");
    } finally {
        try {
            closed = true;
            closing = false;
            transactionEvent.setSuccess(success);
            transactionEvent.setFailure(failure);
            transactionEvent.setTransactionWriteState(writeState.name());
            transactionEvent.setReadOnly(txState == null || !txState.hasChanges());
            transactionEvent.close();
        } finally {
            release();
        }
    }
}
Also used : TransactionFailureException(org.neo4j.internal.kernel.api.exceptions.TransactionFailureException) ConstraintViolationTransactionFailureException(org.neo4j.internal.kernel.api.exceptions.ConstraintViolationTransactionFailureException) KernelException(org.neo4j.exceptions.KernelException) InvalidTransactionTypeKernelException(org.neo4j.internal.kernel.api.exceptions.InvalidTransactionTypeKernelException)

Example 4 with TransactionFailureException

use of org.neo4j.internal.kernel.api.exceptions.TransactionFailureException in project neo4j by neo4j.

the class ConstraintIndexCreator method createUniquenessConstraintIndex.

/**
 * You MUST hold a label write lock before you call this method.
 * However the label 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
 * LABEL 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 LABEL WRITE lock</li>
 * <li>Await index population to complete</li>
 * <li>Acquire the LABEL 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 IndexDescriptor createUniquenessConstraintIndex(KernelTransactionImplementation transaction, IndexBackedConstraintDescriptor constraint, IndexPrototype prototype) throws TransactionFailureException, CreateConstraintFailureException, UniquePropertyValueValidationException, AlreadyConstrainedException {
    String constraintString = constraint.userDescription(transaction.tokenRead());
    log.info("Starting constraint creation: %s.", constraintString);
    IndexDescriptor index;
    SchemaRead schemaRead = transaction.schemaRead();
    try {
        index = checkAndCreateConstraintIndex(schemaRead, transaction.tokenRead(), constraint, prototype);
    } catch (AlreadyConstrainedException e) {
        throw e;
    } catch (KernelException e) {
        throw new CreateConstraintFailureException(constraint, e);
    }
    boolean success = false;
    boolean reacquiredLabelLock = false;
    Client locks = transaction.lockClient();
    ResourceType keyType = constraint.schema().keyType();
    long[] lockingKeys = constraint.schema().lockingKeys();
    try {
        locks.acquireShared(transaction.lockTracer(), keyType, lockingKeys);
        IndexProxy proxy = indexingService.getIndexProxy(index);
        // Release the LABEL 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
        locks.releaseExclusive(keyType, lockingKeys);
        awaitConstraintIndexPopulation(constraint, proxy, transaction);
        log.info("Constraint %s populated, starting verification.", constraintString);
        // Index population was successful, but at this point we don't know if the uniqueness constraint holds.
        // Acquire LABEL 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.
        locks.acquireExclusive(transaction.lockTracer(), keyType, lockingKeys);
        reacquiredLabelLock = true;
        try (NodePropertyAccessor propertyAccessor = new DefaultNodePropertyAccessor(transaction.newStorageReader(), transaction.cursorContext(), transaction.memoryTracker())) {
            indexingService.getIndexProxy(index).verifyDeferredConstraints(propertyAccessor);
        }
        log.info("Constraint %s verified.", constraintString);
        success = true;
        return index;
    } catch (IndexNotFoundKernelException e) {
        String indexString = index.userDescription(transaction.tokenRead());
        throw new TransactionFailureException(format("Index (%s) that we just created does not exist.", indexString), e);
    } catch (IndexEntryConflictException e) {
        throw new UniquePropertyValueValidationException(constraint, VERIFICATION, e, transaction.tokenRead());
    } catch (InterruptedException | IOException e) {
        throw new CreateConstraintFailureException(constraint, e);
    } finally {
        if (!success) {
            if (!reacquiredLabelLock) {
                locks.acquireExclusive(transaction.lockTracer(), keyType, lockingKeys);
            }
            if (indexStillExists(schemaRead, index)) {
                dropUniquenessConstraintIndex(index);
            }
        }
    }
}
Also used : UniquePropertyValueValidationException(org.neo4j.kernel.api.exceptions.schema.UniquePropertyValueValidationException) SchemaRead(org.neo4j.internal.kernel.api.SchemaRead) ResourceType(org.neo4j.lock.ResourceType) IndexNotFoundKernelException(org.neo4j.internal.kernel.api.exceptions.schema.IndexNotFoundKernelException) IOException(java.io.IOException) IndexDescriptor(org.neo4j.internal.schema.IndexDescriptor) NodePropertyAccessor(org.neo4j.storageengine.api.NodePropertyAccessor) DefaultNodePropertyAccessor(org.neo4j.kernel.impl.transaction.state.storeview.DefaultNodePropertyAccessor) DefaultNodePropertyAccessor(org.neo4j.kernel.impl.transaction.state.storeview.DefaultNodePropertyAccessor) TransactionFailureException(org.neo4j.internal.kernel.api.exceptions.TransactionFailureException) AlreadyConstrainedException(org.neo4j.kernel.api.exceptions.schema.AlreadyConstrainedException) IndexProxy(org.neo4j.kernel.impl.api.index.IndexProxy) IndexNotFoundKernelException(org.neo4j.internal.kernel.api.exceptions.schema.IndexNotFoundKernelException) IndexPopulationFailedKernelException(org.neo4j.kernel.api.exceptions.index.IndexPopulationFailedKernelException) KernelException(org.neo4j.exceptions.KernelException) Client(org.neo4j.kernel.impl.locking.Locks.Client) IndexEntryConflictException(org.neo4j.kernel.api.exceptions.index.IndexEntryConflictException) CreateConstraintFailureException(org.neo4j.internal.kernel.api.exceptions.schema.CreateConstraintFailureException)

Example 5 with TransactionFailureException

use of org.neo4j.internal.kernel.api.exceptions.TransactionFailureException in project neo4j by neo4j.

the class TransactionStateMachine method commitTransaction.

@Override
public Bookmark commitTransaction() throws KernelException {
    try {
        BoltTransaction tx = ctx.currentTransaction;
        state = state.commitTransaction(ctx, spi);
        return newestBookmark(spi, tx);
    } catch (TransactionFailureException ex) {
        state = State.AUTO_COMMIT;
        throw ex;
    }
}
Also used : BoltTransaction(org.neo4j.bolt.dbapi.BoltTransaction) TransactionFailureException(org.neo4j.internal.kernel.api.exceptions.TransactionFailureException)

Aggregations

TransactionFailureException (org.neo4j.internal.kernel.api.exceptions.TransactionFailureException)11 Test (org.junit.jupiter.api.Test)5 IOException (java.io.IOException)3 KernelException (org.neo4j.exceptions.KernelException)3 ConstraintViolationTransactionFailureException (org.neo4j.internal.kernel.api.exceptions.ConstraintViolationTransactionFailureException)3 CreateConstraintFailureException (org.neo4j.internal.kernel.api.exceptions.schema.CreateConstraintFailureException)3 IndexDescriptor (org.neo4j.internal.schema.IndexDescriptor)3 KernelTransaction (org.neo4j.kernel.api.KernelTransaction)3 AlreadyConstrainedException (org.neo4j.kernel.api.exceptions.schema.AlreadyConstrainedException)2 UniquePropertyValueValidationException (org.neo4j.kernel.api.exceptions.schema.UniquePropertyValueValidationException)2 TestableTransactionAppender (org.neo4j.kernel.impl.transaction.log.TestableTransactionAppender)2 TransactionAppender (org.neo4j.kernel.impl.transaction.log.TransactionAppender)2 StorageEngine (org.neo4j.storageengine.api.StorageEngine)2 ArrayList (java.util.ArrayList)1 Future (java.util.concurrent.Future)1 Phaser (java.util.concurrent.Phaser)1 ThreadLocalRandom (java.util.concurrent.ThreadLocalRandom)1 AtomicBoolean (java.util.concurrent.atomic.AtomicBoolean)1 AtomicReferenceArray (java.util.concurrent.atomic.AtomicReferenceArray)1 BoltTransaction (org.neo4j.bolt.dbapi.BoltTransaction)1