private SchemaRead SchemaRead()
        {
            SchemaRead schemaRead = mock(typeof(SchemaRead));

            when(schemaRead.Index(_descriptor)).thenReturn(IndexReference.NO_INDEX);
            try
            {
                when(schemaRead.IndexGetCommittedId(_indexReference)).thenReturn(INDEX_ID);
            }
            catch (SchemaKernelException e)
            {
                throw new AssertionError(e);
            }
            return(schemaRead);
        }
Esempio n. 2
0
        /// <summary>
        /// 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>
        /// </summary>
//JAVA TO C# CONVERTER WARNING: Method 'throws' clauses are not available in C#:
//ORIGINAL LINE: public long createUniquenessConstraintIndex(org.neo4j.kernel.impl.api.KernelTransactionImplementation transaction, org.neo4j.internal.kernel.api.schema.SchemaDescriptor descriptor, String provider) throws org.neo4j.internal.kernel.api.exceptions.TransactionFailureException, org.neo4j.internal.kernel.api.exceptions.schema.CreateConstraintFailureException, org.neo4j.kernel.api.exceptions.schema.UniquePropertyValueValidationException, org.neo4j.kernel.api.exceptions.schema.AlreadyConstrainedException
        public virtual long CreateUniquenessConstraintIndex(KernelTransactionImplementation transaction, SchemaDescriptor descriptor, string provider)
        {
            UniquenessConstraintDescriptor constraint = ConstraintDescriptorFactory.uniqueForSchema(descriptor);

            _log.info("Starting constraint creation: %s.", constraint.OwnedIndexDescriptor());

            IndexReference index;
            SchemaRead     schemaRead = transaction.SchemaRead();

            try
            {
                index = GetOrCreateUniquenessConstraintIndex(schemaRead, transaction.TokenRead(), descriptor, provider);
            }
            catch (AlreadyConstrainedException e)
            {
                throw e;
            }
            catch (Exception e) when(e is SchemaKernelException || e is IndexNotFoundKernelException)
            {
                throw new CreateConstraintFailureException(constraint, e);
            }

            bool         success             = false;
            bool         reacquiredLabelLock = false;
            Locks_Client locks = transaction.StatementLocks().pessimistic();

            try
            {
                long       indexId = schemaRead.IndexGetCommittedId(index);
                IndexProxy proxy   = _indexingService.getIndexProxy(indexId);

                // 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(descriptor.KeyType(), descriptor.KeyId());

                AwaitConstraintIndexPopulation(constraint, proxy, transaction);
                _log.info("Constraint %s populated, starting verification.", constraint.OwnedIndexDescriptor());

                // 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(), descriptor.KeyType(), descriptor.KeyId());
                reacquiredLabelLock = true;

                _indexingService.getIndexProxy(indexId).verifyDeferredConstraints(_nodePropertyAccessor);
                _log.info("Constraint %s verified.", constraint.OwnedIndexDescriptor());
                success = true;
                return(indexId);
            }
            catch (SchemaKernelException e)
            {
                throw new System.InvalidOperationException(string.Format("Index ({0}) that we just created does not exist.", descriptor), e);
            }
            catch (IndexNotFoundKernelException e)
            {
                throw new TransactionFailureException(string.Format("Index ({0}) that we just created does not exist.", descriptor), e);
            }
            catch (IndexEntryConflictException e)
            {
                throw new UniquePropertyValueValidationException(constraint, VERIFICATION, e);
            }
            catch (Exception e) when(e is InterruptedException || e is IOException)
            {
                throw new CreateConstraintFailureException(constraint, e);
            }
            finally
            {
                if (!success)
                {
                    if (!reacquiredLabelLock)
                    {
                        locks.AcquireExclusive(transaction.LockTracer(), descriptor.KeyType(), descriptor.KeyId());
                    }

                    if (IndexStillExists(schemaRead, descriptor, index))
                    {
                        DropUniquenessConstraintIndex(( IndexDescriptor )index);
                    }
                }
            }
        }