private PrimitiveLongIterator filterIndexStateChanges(
      KernelStatement state, IndexDescriptor index, Object value, PrimitiveLongIterator nodeIds) {
    if (state.hasTxStateWithChanges()) {
      ReadableDiffSets<Long> labelPropertyChanges = state.txState().indexUpdates(index, value);
      ReadableDiffSets<Long> nodes = state.txState().addedAndRemovedNodes();

      // Apply to actual index lookup
      return nodes.augmentWithRemovals(labelPropertyChanges.augment(nodeIds));
    }
    return nodeIds;
  }
  @Override
  public PrimitiveLongIterator nodesGetForLabel(KernelStatement state, int labelId) {
    if (state.hasTxStateWithChanges()) {
      PrimitiveLongIterator wLabelChanges =
          state
              .txState()
              .nodesWithLabelChanged(labelId)
              .augment(storeLayer.nodesGetForLabel(state, labelId));
      return state.txState().addedAndRemovedNodes().augmentWithRemovals(wLabelChanges);
    }

    return storeLayer.nodesGetForLabel(state, labelId);
  }
  @Override
  public boolean nodeExists(KernelStatement state, long nodeId) {
    if (state.hasTxStateWithChanges()) {
      if (state.txState().nodeIsDeletedInThisTx(nodeId)) {
        return false;
      }

      if (state.txState().nodeIsAddedInThisTx(nodeId)) {
        return true;
      }
    }

    return storeLayer.nodeExists(nodeId);
  }
  @Override
  public boolean relationshipExists(KernelStatement state, long relId) {
    if (state.hasTxStateWithChanges()) {
      if (state.txState().relationshipIsDeletedInThisTx(relId)) {
        return false;
      }

      if (state.txState().relationshipIsAddedInThisTx(relId)) {
        return true;
      }
    }

    return storeLayer.relationshipExists(relId);
  }
 private Iterator<UniquenessConstraint> applyConstraintsDiff(
     KernelStatement state, Iterator<UniquenessConstraint> constraints) {
   if (state.hasTxStateWithChanges()) {
     return state.txState().constraintsChanges().apply(constraints);
   }
   return constraints;
 }
  @Override
  public void relationshipDelete(final KernelStatement state, long relationshipId)
      throws EntityNotFoundException {
    assertRelationshipExists(state, relationshipId);

    // NOTE: We implicitly delegate to neoStoreTransaction via txState.legacyState here. This is
    // because that
    // call returns modified properties, which node manager uses to update legacy tx state. This
    // will be cleaned up
    // once we've removed legacy tx state.
    legacyPropertyTrackers.relationshipDelete(relationshipId);
    final TransactionState txState = state.txState();
    if (txState.relationshipIsAddedInThisTx(relationshipId)) {
      txState.relationshipDoDeleteAddedInThisTx(relationshipId);
    } else {
      try {
        storeLayer.relationshipVisit(
            relationshipId,
            new RelationshipVisitor<RuntimeException>() {
              @Override
              public void visit(long relId, int type, long startNode, long endNode) {
                txState.relationshipDoDelete(relId, type, startNode, endNode);
              }
            });
      } catch (EntityNotFoundException e) {
        // If it doesn't exist, it doesn't exist, and the user got what she wanted.
        return;
      }
    }
  }
  @Override
  public InternalIndexState indexGetState(KernelStatement state, IndexDescriptor descriptor)
      throws IndexNotFoundKernelException {
    // If index is in our state, then return populating
    if (state.hasTxStateWithChanges()) {
      if (checkIndexState(
          descriptor, state.txState().indexDiffSetsByLabel(descriptor.getLabelId()))) {
        return InternalIndexState.POPULATING;
      }
      if (checkIndexState(
          descriptor, state.txState().constraintIndexDiffSetsByLabel(descriptor.getLabelId()))) {
        return InternalIndexState.POPULATING;
      }
    }

    return storeLayer.indexGetState(descriptor);
  }
  @Override
  public Iterator<DefinedProperty> graphGetAllProperties(KernelStatement state) {
    if (state.hasTxStateWithChanges()) {
      return state.txState().augmentGraphProperties(storeLayer.graphGetAllProperties());
    }

    return storeLayer.graphGetAllProperties();
  }
 @Override
 public Property graphRemoveProperty(KernelStatement state, int propertyKeyId) {
   Property existingProperty = graphGetProperty(state, propertyKeyId);
   if (existingProperty.isDefined()) {
     state.txState().graphDoRemoveProperty((DefinedProperty) existingProperty);
   }
   return existingProperty;
 }
  @Override
  public Iterator<IndexDescriptor> uniqueIndexesGetAll(KernelStatement state) {
    if (state.hasTxStateWithChanges()) {
      return state.txState().constraintIndexChanges().apply(storeLayer.uniqueIndexesGetAll());
    }

    return storeLayer.uniqueIndexesGetAll();
  }
  @Override
  public int nodeGetDegree(KernelStatement state, long nodeId, Direction direction)
      throws EntityNotFoundException {
    if (state.hasTxStateWithChanges()) {
      int degree = 0;
      if (state.txState().nodeIsDeletedInThisTx(nodeId)) {
        return 0;
      }

      if (!state.txState().nodeIsAddedInThisTx(nodeId)) {
        degree = storeLayer.nodeGetDegree(nodeId, direction);
      }
      return state.txState().augmentNodeDegree(nodeId, degree, direction);
    } else {
      return storeLayer.nodeGetDegree(nodeId, direction);
    }
  }
 @Override
 public PrimitiveIntIterator nodeGetLabels(KernelStatement state, long nodeId)
     throws EntityNotFoundException {
   if (state.hasTxStateWithChanges()) {
     return nodeGetLabels(storeLayer, state.txState(), nodeId);
   }
   return storeLayer.nodeGetLabels(nodeId);
 }
 @Override
 public void relationshipRemoveFromLegacyIndex(
     KernelStatement statement, String indexName, long relationship, String key, Object value)
     throws LegacyIndexNotFoundKernelException {
   statement
       .txState()
       .getRelationshipLegacyIndexChanges(indexName)
       .remove(relationship, key, value);
 }
  @Override
  public Iterator<DefinedProperty> nodeGetAllProperties(KernelStatement state, long nodeId)
      throws EntityNotFoundException {
    if (state.hasTxStateWithChanges()) {
      if (state.txState().nodeIsAddedInThisTx(nodeId)) {
        return state.txState().addedAndChangedNodeProperties(nodeId);
      }
      if (state.txState().nodeIsDeletedInThisTx(nodeId)) {
        // TODO Throw IllegalStateException to conform with beans API. We may want to introduce
        // EntityDeletedException instead and use it instead of returning empty values in similar
        // places
        throw new IllegalStateException("Node " + nodeId + " has been deleted");
      }
      return state.txState().augmentNodeProperties(nodeId, storeLayer.nodeGetAllProperties(nodeId));
    }

    return storeLayer.nodeGetAllProperties(nodeId);
  }
 @Override
 public long relationshipCreate(
     KernelStatement state, int relationshipTypeId, long startNodeId, long endNodeId)
     throws EntityNotFoundException {
   assertNodeExists(state, startNodeId);
   assertNodeExists(state, endNodeId);
   long id = storeLayer.reserveRelationship();
   state.txState().relationshipDoCreate(id, relationshipTypeId, startNodeId, endNodeId);
   return id;
 }
  private Iterator<UniquenessConstraint> applyConstraintsDiff(
      KernelStatement state, Iterator<UniquenessConstraint> constraints) {
    if (state.hasTxStateWithChanges()) {
      DiffSets<UniquenessConstraint> diff = state.txState().constraintsChanges();
      if (diff != null) {
        return diff.apply(constraints);
      }
    }

    return constraints;
  }
 @Override
 public long countsForNode(KernelStatement statement, int labelId) {
   long count = storeLayer.countsForNode(labelId);
   if (statement.hasTxState()) {
     if (labelId != ReadOperations.ANY_LABEL) {
       throw new UnsupportedOperationException("not implemented");
     }
     count += statement.txState().addedAndRemovedNodes().delta();
   }
   return count;
 }
 // <Legacy index>
 @Override
 public <EXCEPTION extends Exception> void relationshipVisit(
     KernelStatement statement, long relId, RelationshipVisitor<EXCEPTION> visitor)
     throws EntityNotFoundException, EXCEPTION {
   if (statement.hasTxStateWithChanges()) {
     if (statement.txState().relationshipVisit(relId, visitor)) {
       return;
     }
   }
   storeLayer.relationshipVisit(relId, visitor);
 }
 @Override
 public Property nodeRemoveProperty(KernelStatement state, long nodeId, int propertyKeyId)
     throws EntityNotFoundException {
   Property existingProperty = nodeGetProperty(state, nodeId, propertyKeyId);
   if (existingProperty.isDefined()) {
     legacyPropertyTrackers.nodeRemoveStoreProperty(nodeId, (DefinedProperty) existingProperty);
     state.txState().nodeDoRemoveProperty(nodeId, (DefinedProperty) existingProperty);
     indexesUpdateProperty(state, nodeId, propertyKeyId, (DefinedProperty) existingProperty, null);
   }
   return existingProperty;
 }
  @Override
  public Iterator<IndexDescriptor> uniqueIndexesGetForLabel(KernelStatement state, int labelId) {
    if (state.hasTxStateWithChanges()) {
      return state
          .txState()
          .constraintIndexDiffSetsByLabel(labelId)
          .apply(storeLayer.uniqueIndexesGetForLabel(labelId));
    }

    return storeLayer.uniqueIndexesGetForLabel(labelId);
  }
 private void indexUpdateProperty(
     KernelStatement state,
     long nodeId,
     int labelId,
     int propertyKey,
     Object valueBefore,
     Object valueAfter) {
   IndexDescriptor descriptor = indexesGetForLabelAndPropertyKey(state, labelId, propertyKey);
   if (descriptor != null) {
     state.txState().indexUpdateProperty(descriptor, nodeId, valueBefore, valueAfter);
   }
 }
 private void indexUpdateProperty(
     KernelStatement state,
     long nodeId,
     int labelId,
     int propertyKey,
     DefinedProperty before,
     DefinedProperty after) {
   IndexDescriptor descriptor = indexesGetForLabelAndPropertyKey(state, labelId, propertyKey);
   if (descriptor != null) {
     state.txState().indexDoUpdateProperty(descriptor, nodeId, before, after);
   }
 }
  @Override
  public boolean nodeHasLabel(KernelStatement state, long nodeId, int labelId)
      throws EntityNotFoundException {
    if (state.hasTxStateWithChanges()) {
      if (state.txState().nodeIsDeletedInThisTx(nodeId)) {
        return false;
      }

      if (state.txState().nodeIsAddedInThisTx(nodeId)) {
        TxState.UpdateTriState labelState = state.txState().labelState(nodeId, labelId);
        return labelState.isTouched() && labelState.isAdded();
      }

      TxState.UpdateTriState labelState = state.txState().labelState(nodeId, labelId);
      if (labelState.isTouched()) {
        return labelState.isAdded();
      }
    }

    return storeLayer.nodeHasLabel(nodeId, labelId);
  }
  @Override
  public PrimitiveIntIterator nodeGetLabels(KernelStatement state, long nodeId)
      throws EntityNotFoundException {
    if (state.hasTxStateWithChanges()) {
      if (state.txState().nodeIsDeletedInThisTx(nodeId)) {
        return PrimitiveIntCollections.emptyIterator();
      }

      if (state.txState().nodeIsAddedInThisTx(nodeId)) {
        return PrimitiveIntCollections.toPrimitiveIterator(
            state.txState().nodeStateLabelDiffSets(nodeId).getAdded().iterator());
      }

      return state
          .txState()
          .nodeStateLabelDiffSets(nodeId)
          .augment(storeLayer.nodeGetLabels(nodeId));
    }

    return storeLayer.nodeGetLabels(nodeId);
  }
 private Iterator<UniquenessConstraint> applyConstraintsDiff(
     KernelStatement state,
     Iterator<UniquenessConstraint> constraints,
     int labelId,
     int propertyKeyId) {
   if (state.hasTxStateWithChanges()) {
     return state
         .txState()
         .constraintsChangesForLabelAndProperty(labelId, propertyKeyId)
         .apply(constraints);
   }
   return constraints;
 }
  @Override
  public IndexDescriptor indexesGetForLabelAndPropertyKey(
      KernelStatement state, int labelId, int propertyKey) {
    IndexDescriptor indexDescriptor =
        storeLayer.indexesGetForLabelAndPropertyKey(labelId, propertyKey);

    Iterator<IndexDescriptor> rules = iterator(indexDescriptor);
    if (state.hasTxStateWithChanges()) {
      rules =
          filterByPropertyKeyId(
              state.txState().indexDiffSetsByLabel(labelId).apply(rules), propertyKey);
    }
    return singleOrNull(rules);
  }
  @Override
  public boolean nodeHasLabel(KernelStatement state, long nodeId, int labelId)
      throws EntityNotFoundException {
    if (state.hasTxStateWithChanges()) {
      if (state.txState().nodeIsDeletedInThisTx(nodeId)) {
        return false;
      }

      switch (state.txState().labelState(nodeId, labelId)) {
        case ADDED:
          return true;
        case REMOVED:
          return false;
        default: // i.e. UNTOUCHED
          if (state.txState().nodeIsAddedInThisTx(nodeId)) {
            return false;
          }
          // else fall through and return from the store layer
      }
    }

    return storeLayer.nodeHasLabel(nodeId, labelId);
  }
 @Override
 public Property relationshipRemoveProperty(
     KernelStatement state, long relationshipId, int propertyKeyId)
     throws EntityNotFoundException {
   Property existingProperty = relationshipGetProperty(state, relationshipId, propertyKeyId);
   if (existingProperty.isDefined()) {
     legacyPropertyTrackers.relationshipRemoveStoreProperty(
         relationshipId, (DefinedProperty) existingProperty);
     state
         .txState()
         .relationshipDoRemoveProperty(relationshipId, (DefinedProperty) existingProperty);
   }
   return existingProperty;
 }
 @Override
 public LegacyIndexHits relationshipLegacyIndexQuery(
     KernelStatement statement,
     String indexName,
     Object queryOrQueryObject,
     long startNode,
     long endNode)
     throws LegacyIndexNotFoundKernelException {
   LegacyIndex index = statement.txState().getRelationshipLegacyIndexChanges(indexName);
   if (startNode != -1 || endNode != -1) {
     return index.query(queryOrQueryObject, startNode, endNode);
   }
   return index.query(queryOrQueryObject);
 }
  @Override
  public PrimitiveIntIterator nodeGetRelationshipTypes(KernelStatement state, long nodeId)
      throws EntityNotFoundException {
    if (state.hasTxStateWithChanges() && state.txState().nodeModifiedInThisTx(nodeId)) {
      ReadableTxState tx = state.txState();
      if (tx.nodeIsDeletedInThisTx(nodeId)) {
        return PrimitiveIntCollections.emptyIterator();
      }

      if (tx.nodeIsAddedInThisTx(nodeId)) {
        return tx.nodeRelationshipTypes(nodeId);
      }

      Set<Integer> types = new HashSet<>();

      // Add types in the current transaction
      PrimitiveIntIterator typesInTx = tx.nodeRelationshipTypes(nodeId);
      while (typesInTx.hasNext()) {
        types.add(typesInTx.next());
      }

      // Augment with types stored on disk, minus any types where all rels of that type are deleted
      // in current tx.
      PrimitiveIntIterator committedTypes = storeLayer.nodeGetRelationshipTypes(nodeId);
      while (committedTypes.hasNext()) {
        int current = committedTypes.next();
        if (!types.contains(current) && nodeGetDegree(state, nodeId, Direction.BOTH, current) > 0) {
          types.add(current);
        }
      }

      return PrimitiveIntCollections.toPrimitiveIterator(types.iterator());
    } else {
      return storeLayer.nodeGetRelationshipTypes(nodeId);
    }
  }