All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.neo4j.kernel.impl.newapi.AllStoreHolder Maven / Gradle / Ivy

Go to download

Neo4j kernel is a lightweight, embedded Java database designed to store data structured as graphs rather than tables. For more information, see http://neo4j.org.

There is a newer version: 5.25.1
Show newest version
/*
 * Copyright (c) "Neo4j"
 * Neo4j Sweden AB [https://neo4j.com]
 *
 * This file is part of Neo4j.
 *
 * Neo4j is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program.  If not, see .
 */
package org.neo4j.kernel.impl.newapi;

import static org.neo4j.internal.helpers.collection.Iterators.singleOrNull;

import java.util.Collections;
import java.util.Iterator;
import java.util.List;
import java.util.Objects;
import java.util.Set;
import java.util.function.Function;
import java.util.function.Predicate;
import java.util.function.Supplier;
import java.util.stream.Stream;
import org.neo4j.collection.Dependencies;
import org.neo4j.collection.RawIterator;
import org.neo4j.collection.diffset.DiffSets;
import org.neo4j.common.EntityType;
import org.neo4j.exceptions.KernelException;
import org.neo4j.internal.helpers.collection.Iterators;
import org.neo4j.internal.kernel.api.IndexMonitor;
import org.neo4j.internal.kernel.api.IndexReadSession;
import org.neo4j.internal.kernel.api.InternalIndexState;
import org.neo4j.internal.kernel.api.NodeValueIndexCursor;
import org.neo4j.internal.kernel.api.PopulationProgress;
import org.neo4j.internal.kernel.api.PropertyIndexQuery;
import org.neo4j.internal.kernel.api.RelationshipValueIndexCursor;
import org.neo4j.internal.kernel.api.SchemaReadCore;
import org.neo4j.internal.kernel.api.TokenRead;
import org.neo4j.internal.kernel.api.TokenReadSession;
import org.neo4j.internal.kernel.api.exceptions.ProcedureException;
import org.neo4j.internal.kernel.api.exceptions.schema.IndexNotFoundKernelException;
import org.neo4j.internal.kernel.api.procs.ProcedureCallContext;
import org.neo4j.internal.kernel.api.procs.ProcedureHandle;
import org.neo4j.internal.kernel.api.procs.ProcedureSignature;
import org.neo4j.internal.kernel.api.procs.QualifiedName;
import org.neo4j.internal.kernel.api.procs.UserAggregationReducer;
import org.neo4j.internal.kernel.api.procs.UserFunctionHandle;
import org.neo4j.internal.kernel.api.procs.UserFunctionSignature;
import org.neo4j.internal.kernel.api.security.AccessMode;
import org.neo4j.internal.kernel.api.security.SecurityAuthorizationHandler;
import org.neo4j.internal.schema.ConstraintDescriptor;
import org.neo4j.internal.schema.IndexDescriptor;
import org.neo4j.internal.schema.IndexType;
import org.neo4j.internal.schema.SchemaDescriptor;
import org.neo4j.internal.schema.SchemaDescriptors;
import org.neo4j.internal.schema.SchemaState;
import org.neo4j.io.pagecache.context.CursorContext;
import org.neo4j.kernel.api.index.IndexSample;
import org.neo4j.kernel.api.index.IndexUsageStats;
import org.neo4j.kernel.api.index.TokenIndexReader;
import org.neo4j.kernel.api.index.ValueIndexReader;
import org.neo4j.kernel.api.procedure.ProcedureView;
import org.neo4j.kernel.api.txstate.TransactionState;
import org.neo4j.kernel.impl.api.ClockContext;
import org.neo4j.kernel.impl.api.IndexReaderCache;
import org.neo4j.kernel.impl.api.KernelTransactionImplementation;
import org.neo4j.kernel.impl.api.OverridableSecurityContext;
import org.neo4j.kernel.impl.api.index.IndexingService;
import org.neo4j.kernel.impl.api.index.stats.IndexStatisticsStore;
import org.neo4j.kernel.impl.api.parallel.ExecutionContextProcedureKernelTransaction;
import org.neo4j.kernel.impl.api.parallel.ParallelAccessCheck;
import org.neo4j.kernel.impl.api.parallel.ThreadExecutionContext;
import org.neo4j.kernel.impl.locking.LockManager;
import org.neo4j.kernel.impl.locking.LockManager.Client;
import org.neo4j.lock.LockTracer;
import org.neo4j.lock.ResourceType;
import org.neo4j.memory.MemoryTracker;
import org.neo4j.storageengine.api.StorageLocks;
import org.neo4j.storageengine.api.StorageReader;
import org.neo4j.storageengine.api.StorageSchemaReader;
import org.neo4j.storageengine.api.cursor.StoreCursors;
import org.neo4j.values.AnyValue;
import org.neo4j.values.storable.Value;

/**
 * Implementation of read operation of the Kernel API.
 * 

* The relation between a transaction and All Store Holder can be one to many * and the instances of All Store Holder related to the same transaction can be used concurrently by multiple threads. * The thread safety aspect of the operation performed by All Store Holder must reflect it! * This means that All Store Holder must not use objects shared by multiple All Store Holders that are * not safe for multithreaded use!!! * This class has two implementations. * {@link ForTransactionScope} has one-to-one relation with a transaction and therefore it can safely * use {@link KernelTransactionImplementation}, its resources and generally any transaction-scoped resource * {@link ForThreadExecutionContextScope} has one-to-many relation with a transaction and therefore it CANNOT safely * use {@link KernelTransactionImplementation}, its resources and generally any transaction-scoped * resource which is not designed for concurrent use. * It should use resources in {@link org.neo4j.kernel.impl.api.parallel.ThreadExecutionContext} scope instead. */ public abstract class AllStoreHolder extends Read { private final SchemaState schemaState; private final IndexingService indexingService; private final IndexStatisticsStore indexStatisticsStore; private final MemoryTracker memoryTracker; private final IndexReaderCache valueIndexReaderCache; private final IndexReaderCache tokenIndexReaderCache; private final EntityCounter entityCounter; private final boolean applyAccessModeToTxState; private AllStoreHolder( StorageReader storageReader, TokenRead tokenRead, SchemaState schemaState, IndexingService indexingService, IndexStatisticsStore indexStatisticsStore, MemoryTracker memoryTracker, DefaultPooledCursors cursors, StoreCursors storageCursors, StorageLocks storageLocks, LockTracer lockTracer, boolean multiVersioned) { super(storageReader, tokenRead, cursors, storageCursors, storageLocks, lockTracer); this.schemaState = schemaState; this.valueIndexReaderCache = new IndexReaderCache<>( index -> indexingService.getIndexProxy(index).newValueReader()); this.tokenIndexReaderCache = new IndexReaderCache<>( index -> indexingService.getIndexProxy(index).newTokenReader()); this.indexingService = indexingService; this.indexStatisticsStore = indexStatisticsStore; this.memoryTracker = memoryTracker; this.entityCounter = new EntityCounter(multiVersioned); this.applyAccessModeToTxState = multiVersioned; } @Override public boolean nodeExists(long reference) { performCheckBeforeOperation(); if (hasTxStateWithChanges()) { TransactionState txState = txState(); if (txState.nodeIsDeletedInThisBatch(reference)) { return false; } else if (txState.nodeIsAddedInThisBatch(reference)) { return true; } } boolean existsInNodeStore = storageReader.nodeExists(reference, storageCursors); if (getAccessMode().allowsTraverseAllLabels()) { return existsInNodeStore; } else if (!existsInNodeStore) { return false; } else { try (DefaultNodeCursor node = cursors.allocateNodeCursor(cursorContext(), memoryTracker())) { singleNode(reference, node); return node.next(); } } } @Override public boolean nodeDeletedInTransaction(long node) { performCheckBeforeOperation(); return hasTxStateWithChanges() && txState().nodeIsDeletedInThisBatch(node); } @Override public boolean relationshipDeletedInTransaction(long relationship) { performCheckBeforeOperation(); return hasTxStateWithChanges() && txState().relationshipIsDeletedInThisBatch(relationship); } @Override public Value nodePropertyChangeInBatchOrNull(long node, int propertyKeyId) { performCheckBeforeOperation(); return hasTxStateWithChanges() ? txState().getNodeState(node).propertyValue(propertyKeyId) : null; } @Override public Value relationshipPropertyChangeInBatchOrNull(long relationship, int propertyKeyId) { performCheckBeforeOperation(); return hasTxStateWithChanges() ? txState().getRelationshipState(relationship).propertyValue(propertyKeyId) : null; } @Override public long countsForNode(int labelId) { return entityCounter.countsForNode( labelId, getAccessMode(), storageReader, cursors, cursorContext(), memoryTracker(), this, storageCursors); } @Override public List mostCommonLabelGivenRelationshipType(int type) { return entityCounter.mostCommonLabelGivenRelationshipType(type, storageReader, cursorContext()); } @Override public long estimateCountsForNode(int labelId) { return storageReader.estimateCountsForNode(labelId, cursorContext()); } @Override public long countsForRelationship(int startLabelId, int typeId, int endLabelId) { return entityCounter.countsForRelationship( startLabelId, typeId, endLabelId, getAccessMode(), storageReader, cursors, this, cursorContext(), memoryTracker(), storageCursors); } @Override public long estimateCountsForRelationships(int startLabelId, int typeId, int endLabelId) { return storageReader.estimateCountsForRelationship(startLabelId, typeId, endLabelId, cursorContext()); } IndexDescriptor findUsableTokenIndex(EntityType entityType) throws IndexNotFoundKernelException { var descriptor = SchemaDescriptors.forAnyEntityTokens(entityType); var index = index(descriptor, IndexType.LOOKUP); if (index != IndexDescriptor.NO_INDEX && indexGetState(index) == InternalIndexState.ONLINE) { return index; } return IndexDescriptor.NO_INDEX; } @Override public boolean relationshipExists(long reference) { performCheckBeforeOperation(); if (hasTxStateWithChanges()) { TransactionState txState = txState(); if (txState.relationshipIsDeletedInThisBatch(reference)) { return false; } else if (txState.relationshipIsAddedInThisBatch(reference)) { return true; } } boolean existsInRelStore = storageReader.relationshipExists(reference, storageCursors); if (getAccessMode().allowsTraverseAllRelTypes()) { return existsInRelStore; } else if (!existsInRelStore) { return false; } else { try (DefaultRelationshipScanCursor rels = cursors.allocateRelationshipScanCursor(cursorContext(), memoryTracker())) { singleRelationship(reference, rels); return rels.next(); } } } @Override public ValueIndexReader newValueIndexReader(IndexDescriptor index) throws IndexNotFoundKernelException { assertValidIndex(index); return indexingService.getIndexProxy(index).newValueReader(); } public TokenIndexReader newTokenIndexReader(IndexDescriptor index) throws IndexNotFoundKernelException { assertValidIndex(index); return indexingService.getIndexProxy(index).newTokenReader(); } @Override public IndexReadSession indexReadSession(IndexDescriptor index) throws IndexNotFoundKernelException { assertValidIndex(index); return new DefaultIndexReadSession(valueIndexReaderCache.getOrCreate(index), index); } @Override public TokenReadSession tokenReadSession(IndexDescriptor index) throws IndexNotFoundKernelException { assertValidIndex(index); return new DefaultTokenReadSession(tokenIndexReaderCache.getOrCreate(index), index); } @Override public Iterator indexForSchemaNonTransactional(SchemaDescriptor schema) { return storageReader.indexGetForSchema(schema); } @Override public IndexDescriptor indexForSchemaAndIndexTypeNonTransactional(SchemaDescriptor schema, IndexType indexType) { var index = storageReader.indexGetForSchemaAndType(schema, indexType); return index == null ? IndexDescriptor.NO_INDEX : index; } @Override public Iterator indexForSchemaNonLocking(SchemaDescriptor schema) { return indexGetForSchema(storageReader, schema); } @Override public Iterator getLabelIndexesNonLocking(int labelId) { return indexesGetForLabel(storageReader, labelId); } @Override public Iterator getRelTypeIndexesNonLocking(int relTypeId) { return indexesGetForRelationshipType(storageReader, relTypeId); } @Override public Iterator indexesGetAllNonLocking() { return indexesGetAll(storageReader); } /** * Lock the given index if it is valid and exists. * If the given index descriptor does not reference an index that exists, then {@link IndexDescriptor#NO_INDEX} is returned. * * @param index committed, transaction-added or even null. * @return The validated index descriptor, which is not necessarily the same as the one given as an argument. */ private IndexDescriptor lockIndex(IndexDescriptor index) { if (index == null) { return IndexDescriptor.NO_INDEX; } index = acquireSharedSchemaLock(index); // Since the schema cache gives us snapshots views of the schema, the indexes could be dropped in-between us // getting the snapshot, and taking the shared schema locks. // Thus, after we take the lock, we need to filter out indexes that no longer exists. if (!indexExists(index)) { releaseSharedSchemaLock(index); index = IndexDescriptor.NO_INDEX; } return index; } /** * Maps all index descriptors according to {@link #lockIndex(IndexDescriptor)}. */ private Iterator lockIndexes(Iterator indexes) { Predicate exists = index -> index != IndexDescriptor.NO_INDEX; return Iterators.filter(exists, Iterators.map(this::lockIndex, indexes)); } private boolean indexExists(IndexDescriptor index) { if (hasTxStateWithChanges()) { DiffSets changes = txState().indexChanges(); return changes.isAdded(index) || (storageReader.indexExists(index) && !changes.isRemoved(index)); } return storageReader.indexExists(index); } public void assertIndexExists(IndexDescriptor index) throws IndexNotFoundKernelException { if (!indexExists(index)) { throw new IndexNotFoundKernelException("Index does not exist: ", index); } } private ConstraintDescriptor lockConstraint(ConstraintDescriptor constraint) { if (constraint == null) { return null; } constraint = acquireSharedSchemaLock(constraint); if (!constraintExists(constraint)) { releaseSharedSchemaLock(constraint); constraint = null; } return constraint; } private Iterator lockConstraints(Iterator constraints) { return Iterators.filter(Objects::nonNull, Iterators.map(this::lockConstraint, constraints)); } @Override public boolean constraintExists(ConstraintDescriptor constraint) { acquireSharedSchemaLock(constraint); performCheckBeforeOperation(); if (hasTxStateWithChanges()) { DiffSets changes = txState().constraintsChanges(); return changes.isAdded(constraint) || (storageReader.constraintExists(constraint) && !changes.isRemoved(constraint)); } return storageReader.constraintExists(constraint); } @Override public Iterator index(SchemaDescriptor schema) { performCheckBeforeOperation(); return lockIndexes(indexGetForSchema(storageReader, schema)); } Iterator indexGetForSchema(StorageSchemaReader reader, SchemaDescriptor schema) { Iterator indexes = reader.indexGetForSchema(schema); if (hasTxStateWithChanges()) { DiffSets diffSets = txState().indexDiffSetsBySchema(schema); indexes = diffSets.apply(indexes); } return indexes; } @Override public IndexDescriptor index(SchemaDescriptor schema, IndexType type) { performCheckBeforeOperation(); return lockIndex(indexGetForSchemaAndType(storageReader, schema, type)); } IndexDescriptor indexGetForSchemaAndType(StorageSchemaReader reader, SchemaDescriptor schema, IndexType type) { var index = reader.indexGetForSchemaAndType(schema, type); if (hasTxStateWithChanges()) { var indexChanges = txState().indexChanges(); if (index == null) { // check if such index was added in this tx var added = indexChanges .filterAdded( id -> id.getIndexType() == type && id.schema().equals(schema)) .getAdded(); index = singleOrNull(added.iterator()); } if (indexChanges.isRemoved(index)) { // this index was removed in this tx return null; } } return index; } @Override public Iterator indexesGetForLabel(int labelId) { acquireSharedLock(ResourceType.LABEL, labelId); performCheckBeforeOperation(); return lockIndexes(indexesGetForLabel(storageReader, labelId)); } Iterator indexesGetForLabel(StorageSchemaReader reader, int labelId) { AccessMode accessMode = getAccessMode(); if (accessMode.allowsTraverseNode(labelId) || accessMode.hasApplicableTraverseAllowPropertyRules(labelId)) { Iterator iterator = reader.indexesGetForLabel(labelId); if (hasTxStateWithChanges()) { iterator = txState().indexDiffSetsByLabel(labelId).apply(iterator); } return iterator; } else { return Collections.emptyIterator(); } } @Override public Iterator indexesGetForRelationshipType(int relationshipType) { acquireSharedLock(ResourceType.RELATIONSHIP_TYPE, relationshipType); performCheckBeforeOperation(); return lockIndexes(indexesGetForRelationshipType(storageReader, relationshipType)); } Iterator indexesGetForRelationshipType(StorageSchemaReader reader, int relationshipType) { Iterator iterator = reader.indexesGetForRelationshipType(relationshipType); if (hasTxStateWithChanges()) { iterator = txState().indexDiffSetsByRelationshipType(relationshipType).apply(iterator); } return iterator; } @Override public IndexDescriptor indexGetForName(String name) { return indexGetForName(storageReader, name); } IndexDescriptor indexGetForName(StorageSchemaReader reader, String name) { performCheckBeforeOperation(); IndexDescriptor index = reader.indexGetForName(name); if (hasTxStateWithChanges()) { Predicate namePredicate = indexDescriptor -> indexDescriptor.getName().equals(name); Iterator indexes = txState().indexChanges().filterAdded(namePredicate).apply(Iterators.iterator(index)); index = singleOrNull(indexes); } return lockIndex(index); } @Override public ConstraintDescriptor constraintGetForName(String name) { return constraintGetForName(storageReader, name); } ConstraintDescriptor constraintGetForName(StorageSchemaReader reader, String name) { performCheckBeforeOperation(); ConstraintDescriptor constraint = reader.constraintGetForName(name); if (hasTxStateWithChanges()) { Predicate namePredicate = constraintDescriptor -> constraintDescriptor.getName().equals(name); Iterator constraints = txState().constraintsChanges().filterAdded(namePredicate).apply(Iterators.iterator(constraint)); constraint = singleOrNull(constraints); } return lockConstraint(constraint); } @Override public Iterator indexesGetAll() { performCheckBeforeOperation(); Iterator iterator = indexesGetAll(storageReader); return lockIndexes(iterator); } Iterator indexesGetAll(StorageSchemaReader reader) { Iterator iterator = reader.indexesGetAll(); if (hasTxStateWithChanges()) { iterator = txState().indexChanges().apply(iterator); } return iterator; } @Override public InternalIndexState indexGetState(IndexDescriptor index) throws IndexNotFoundKernelException { assertValidIndex(index); acquireSharedSchemaLock(index); performCheckBeforeOperation(); return indexGetStateLocked(index); } @Override public InternalIndexState indexGetStateNonLocking(IndexDescriptor index) throws IndexNotFoundKernelException { assertValidIndex(index); performCheckBeforeOperation(); return indexGetStateLocked( index); // TODO: Can we call this method without locking(since we assert valid index)? } InternalIndexState indexGetStateLocked(IndexDescriptor index) throws IndexNotFoundKernelException { SchemaDescriptor schema = index.schema(); // If index is in our state, then return populating if (hasTxStateWithChanges()) { if (checkIndexState(index, txState().indexDiffSetsBySchema(schema))) { return InternalIndexState.POPULATING; } } return indexingService.getIndexProxy(index).getState(); } @Override public PopulationProgress indexGetPopulationProgress(IndexDescriptor index) throws IndexNotFoundKernelException { assertValidIndex(index); acquireSharedSchemaLock(index); performCheckBeforeOperation(); return indexGetPopulationProgressLocked(index); } PopulationProgress indexGetPopulationProgressLocked(IndexDescriptor index) throws IndexNotFoundKernelException { if (hasTxStateWithChanges()) { if (checkIndexState(index, txState().indexDiffSetsBySchema(index.schema()))) { return PopulationProgress.NONE; } } return indexingService.getIndexProxy(index).getIndexPopulationProgress(); } @Override public Long indexGetOwningUniquenessConstraintId(IndexDescriptor index) { acquireSharedSchemaLock(index); return indexGetOwningUniquenessConstraintIdNonLocking(index); } @Override public Long indexGetOwningUniquenessConstraintIdNonLocking(IndexDescriptor index) { performCheckBeforeOperation(); return storageReader.indexGetOwningUniquenessConstraintId(storageReader.indexGetForName(index.getName())); } @Override public String indexGetFailure(IndexDescriptor index) throws IndexNotFoundKernelException { assertValidIndex(index); return indexingService.getIndexProxy(index).getPopulationFailure().asString(); } @Override public double indexUniqueValuesSelectivity(IndexDescriptor index) throws IndexNotFoundKernelException { performCheckBeforeOperation(); assertValidIndex(index); acquireSharedSchemaLock(index); assertIndexExists(index); // Throws if the index has been dropped. final IndexSample indexSample = indexStatisticsStore.indexSample(index.getId()); long unique = indexSample.uniqueValues(); long size = indexSample.sampleSize(); return size == 0 ? 1.0d : ((double) unique) / ((double) size); } @Override public long indexSize(IndexDescriptor index) throws IndexNotFoundKernelException { performCheckBeforeOperation(); assertValidIndex(index); acquireSharedSchemaLock(index); return indexStatisticsStore.indexSample(index.getId()).indexSize(); } @Override public IndexUsageStats indexUsageStats(IndexDescriptor index) throws IndexNotFoundKernelException { performCheckBeforeOperation(); assertValidIndex(index); return indexStatisticsStore.usageStats(index.getId()); } @Override public long nodesGetCount() { return countsForNode(TokenRead.ANY_LABEL); } @Override public long relationshipsGetCount() { return countsForRelationship(TokenRead.ANY_LABEL, TokenRead.ANY_RELATIONSHIP_TYPE, TokenRead.ANY_LABEL); } @Override public IndexSample indexSample(IndexDescriptor index) throws IndexNotFoundKernelException { performCheckBeforeOperation(); assertValidIndex(index); return indexStatisticsStore.indexSample(index.getId()); } private static boolean checkIndexState(IndexDescriptor index, DiffSets diffSet) throws IndexNotFoundKernelException { if (diffSet.isAdded(index)) { return true; } if (diffSet.isRemoved(index)) { throw new IndexNotFoundKernelException("Index has been dropped in this transaction: ", index); } return false; } @Override public Iterator constraintsGetForSchema(SchemaDescriptor schema) { acquireSharedSchemaLock(() -> schema); return getConstraintsForSchema(schema); } @Override public Iterator constraintsGetForSchemaNonLocking(SchemaDescriptor schema) { return getConstraintsForSchema(schema); } private Iterator getConstraintsForSchema(SchemaDescriptor schema) { performCheckBeforeOperation(); Iterator constraints = storageReader.constraintsGetForSchema(schema); if (hasTxStateWithChanges()) { return txState().constraintsChangesForSchema(schema).apply(constraints); } return constraints; } @Override public Iterator constraintsGetForLabel(int labelId) { performCheckBeforeOperation(); acquireSharedLock(ResourceType.LABEL, labelId); return constraintsGetForLabel(storageReader, labelId); } @Override public Iterator constraintsGetForLabelNonLocking(int labelId) { performCheckBeforeOperation(); return constraintsGetForLabel(storageReader, labelId); } Iterator constraintsGetForLabel(StorageSchemaReader reader, int labelId) { Iterator constraints = reader.constraintsGetForLabel(labelId); if (hasTxStateWithChanges()) { return txState().constraintsChangesForLabel(labelId).apply(constraints); } return constraints; } @Override public Iterator constraintsGetAll() { performCheckBeforeOperation(); Iterator constraints = constraintsGetAll(storageReader); return lockConstraints(constraints); } @Override public Iterator constraintsGetAllNonLocking() { performCheckBeforeOperation(); return constraintsGetAll(storageReader); } Iterator constraintsGetAll(StorageSchemaReader reader) { Iterator constraints = reader.constraintsGetAll(); if (hasTxStateWithChanges()) { constraints = txState().constraintsChanges().apply(constraints); } return constraints; } @Override public Iterator constraintsGetForRelationshipType(int typeId) { performCheckBeforeOperation(); acquireSharedLock(ResourceType.RELATIONSHIP_TYPE, typeId); return constraintsGetForRelationshipType(storageReader, typeId); } @Override public Iterator constraintsGetForRelationshipTypeNonLocking(int typeId) { performCheckBeforeOperation(); return constraintsGetForRelationshipType(storageReader, typeId); } Iterator constraintsGetForRelationshipType(StorageSchemaReader reader, int typeId) { Iterator constraints = reader.constraintsGetForRelationshipType(typeId); if (hasTxStateWithChanges()) { return txState().constraintsChangesForRelationshipType(typeId).apply(constraints); } return constraints; } @Override public SchemaReadCore snapshot() { performCheckBeforeOperation(); StorageSchemaReader snapshot = storageReader.schemaSnapshot(); return new SchemaReadCoreSnapshot(snapshot, this); } @Override public V schemaStateGetOrCreate(K key, Function creator) { return schemaState.getOrCreate(key, creator); } @Override public void schemaStateFlush() { schemaState.clear(); } @Override public boolean transactionStateHasChanges() { return hasTxStateWithChanges(); } static void assertValidIndex(IndexDescriptor index) throws IndexNotFoundKernelException { if (index == IndexDescriptor.NO_INDEX) { throw new IndexNotFoundKernelException("No index was found"); } } public void release() { // Note: This only clears the caches, and does in fact not close the objects valueIndexReaderCache.close(); tokenIndexReaderCache.close(); } abstract ProcedureCaller getProcedureCaller(); @Override public MemoryTracker memoryTracker() { return memoryTracker; } @Override public IndexMonitor monitor() { return indexingService.getMonitor(); } @Override public RawIterator procedureCallRead( int id, AnyValue[] arguments, ProcedureCallContext context) throws ProcedureException { return getProcedureCaller().callProcedure(id, arguments, AccessMode.Static.READ, context); } @Override public RawIterator procedureCallWrite( int id, AnyValue[] arguments, ProcedureCallContext context) throws ProcedureException { return getProcedureCaller().callProcedure(id, arguments, AccessMode.Static.TOKEN_WRITE, context); } @Override public RawIterator procedureCallSchema( int id, AnyValue[] arguments, ProcedureCallContext context) throws ProcedureException { return getProcedureCaller().callProcedure(id, arguments, AccessMode.Static.SCHEMA, context); } @Override public RawIterator procedureCallDbms( int id, AnyValue[] arguments, ProcedureCallContext context) throws ProcedureException { return getProcedureCaller().callProcedure(id, arguments, AccessMode.Static.ACCESS, context); } @Override public AnyValue functionCall(int id, AnyValue[] arguments, ProcedureCallContext context) throws ProcedureException { return getProcedureCaller().callFunction(id, arguments, context); } @Override public AnyValue builtInFunctionCall(int id, AnyValue[] arguments, ProcedureCallContext context) throws ProcedureException { return getProcedureCaller().callBuiltInFunction(id, arguments, context); } @Override public UserAggregationReducer aggregationFunction(int id, ProcedureCallContext context) throws ProcedureException { return getProcedureCaller().createAggregationFunction(id, context); } @Override public UserAggregationReducer builtInAggregationFunction(int id, ProcedureCallContext context) throws ProcedureException { return getProcedureCaller().createBuiltInAggregationFunction(id, context); } @Override public UserFunctionHandle functionGet(QualifiedName name) { performCheckBeforeOperation(); return getProcedureCaller().procedureView.function(name); } @Override public Stream functionGetAll() { performCheckBeforeOperation(); return getProcedureCaller().procedureView.getAllNonAggregatingFunctions(); } @Override public ProcedureHandle procedureGet(QualifiedName name) throws ProcedureException { performCheckBeforeOperation(); return getProcedureCaller().procedureView.procedure(name); } @Override public Set proceduresGetAll() { performCheckBeforeOperation(); return getProcedureCaller().procedureView.getAllProcedures(); } @Override public UserFunctionHandle aggregationFunctionGet(QualifiedName name) { performCheckBeforeOperation(); return getProcedureCaller().procedureView.aggregationFunction(name); } @Override public Stream aggregationFunctionGetAll() { performCheckBeforeOperation(); return getProcedureCaller().procedureView.getAllAggregatingFunctions(); } @Override public long signatureVersion() { return getProcedureCaller().procedureView.signatureVersion(); } public static class ForTransactionScope extends AllStoreHolder { private final KernelTransactionImplementation ktx; private final Dependencies databaseDependencies; private ProcedureCaller.ForTransactionScope procedureCaller; public ForTransactionScope( StorageReader storageReader, TokenRead tokenRead, KernelTransactionImplementation ktx, StorageLocks storageLocks, DefaultPooledCursors cursors, SchemaState schemaState, IndexingService indexingService, IndexStatisticsStore indexStatisticsStore, Dependencies databaseDependencies, MemoryTracker memoryTracker, boolean multiVersioned) { super( storageReader, tokenRead, schemaState, indexingService, indexStatisticsStore, memoryTracker, cursors, ktx.storeCursors(), storageLocks, ktx.lockTracer(), multiVersioned); this.ktx = ktx; this.databaseDependencies = databaseDependencies; } public void initialize(ProcedureView procedureView) { this.procedureCaller = new ProcedureCaller.ForTransactionScope(ktx, databaseDependencies, procedureView); } @Override public TransactionState txState() { return ktx.txState(); } @Override public boolean hasTxStateWithChanges() { return ktx.hasTxStateWithChanges(); } @Override void performCheckBeforeOperation() { if (ParallelAccessCheck.shouldPerformCheck()) { ParallelAccessCheck.checkNotCypherWorkerThread(); } ktx.assertOpen(); } @Override AccessMode getAccessMode() { return ktx.securityContext().mode(); } @Override LockManager.Client getLockClient() { // lock client has to be accessed like this, because of KernelTransaction#freezeLocks return ktx.lockClient(); } @Override public CursorContext cursorContext() { return ktx.cursorContext(); } public void close() { procedureCaller = null; } @Override ProcedureCaller getProcedureCaller() { return procedureCaller; } } public static class ForThreadExecutionContextScope extends AllStoreHolder { private final OverridableSecurityContext overridableSecurityContext; private final CursorContext cursorContext; private final LockManager.Client lockClient; private final ExecutionContextProcedureKernelTransaction kernelTransaction; private final ProcedureCaller.ForThreadExecutionContextScope procedureCaller; public ForThreadExecutionContextScope( ThreadExecutionContext executionContext, StorageReader storageReader, SchemaState schemaState, IndexingService indexingService, IndexStatisticsStore indexStatisticsStore, Dependencies databaseDependencies, DefaultPooledCursors cursors, StoreCursors storageCursors, CursorContext cursorContext, StorageLocks storageLocks, Client lockClient, LockTracer lockTracer, OverridableSecurityContext overridableSecurityContext, ExecutionContextProcedureKernelTransaction kernelTransaction, SecurityAuthorizationHandler securityAuthorizationHandler, Supplier clockContextSupplier, ProcedureView procedureView, boolean multiVersioned) { super( storageReader, executionContext.tokenRead(), schemaState, indexingService, indexStatisticsStore, executionContext.memoryTracker(), cursors, storageCursors, storageLocks, lockTracer, multiVersioned); this.overridableSecurityContext = overridableSecurityContext; this.cursorContext = cursorContext; this.lockClient = lockClient; this.kernelTransaction = kernelTransaction; this.procedureCaller = new ProcedureCaller.ForThreadExecutionContextScope( executionContext, databaseDependencies, overridableSecurityContext, kernelTransaction, securityAuthorizationHandler, clockContextSupplier, procedureView); } @Override public long lockingNodeUniqueIndexSeek( IndexDescriptor index, NodeValueIndexCursor cursor, PropertyIndexQuery.ExactPredicate... predicates) { // This is currently a problematic operation for parallel execution, because it takes exclusive locks. // In transactions deadlocks is a problem for another day :) . throw new UnsupportedOperationException("Locking unique index seek not allowed during parallel execution"); } @Override public long lockingRelationshipUniqueIndexSeek( IndexDescriptor index, RelationshipValueIndexCursor cursor, PropertyIndexQuery.ExactPredicate... predicates) throws KernelException { // This is currently a problematic operation for parallel execution, because it takes exclusive locks. // In transactions deadlocks is a problem for another day :) . throw new UnsupportedOperationException("Locking unique index seek not allowed during parallel execution"); } @Override public RawIterator procedureCallWrite( int id, AnyValue[] arguments, ProcedureCallContext context) { throw new UnsupportedOperationException( "Invoking procedure with WRITE access mode is not allowed during parallel execution."); } @Override public RawIterator procedureCallSchema( int id, AnyValue[] arguments, ProcedureCallContext context) { throw new UnsupportedOperationException( "Invoking procedure with SCHEMA access mode is not allowed during parallel execution."); } @Override public TransactionState txState() { throw new UnsupportedOperationException( "Accessing transaction state is not allowed during parallel execution"); } @Override public boolean hasTxStateWithChanges() { return false; } @Override void performCheckBeforeOperation() { kernelTransaction.assertOpen(); } @Override AccessMode getAccessMode() { return overridableSecurityContext.currentSecurityContext().mode(); } @Override LockManager.Client getLockClient() { return lockClient; } @Override public CursorContext cursorContext() { return cursorContext; } @Override ProcedureCaller getProcedureCaller() { return procedureCaller; } } }





© 2015 - 2024 Weber Informatics LLC | Privacy Policy