/// <summary> /// Efficiently visits changed nodes, e.g. nodes that have had any relationship chain updated by /// <seealso cref="getAndPutRelationship(long, int, Direction, long, bool)"/>. /// </summary> /// <param name="visitor"> <seealso cref="NodeChangeVisitor"/> which will be notified about all changes. </param> /// <param name="nodeTypes"> which types to visit (dense/sparse). </param> public virtual void VisitChangedNodes(NodeChangeVisitor visitor, int nodeTypes) { long denseMask = ChangeMask(true); long sparseMask = ChangeMask(false); sbyte denseChunkMask = ChunkChangeMask(true); sbyte sparseChunkMask = ChunkChangeMask(false); for (long nodeId = 0; nodeId < _highNodeId;) { bool chunkHasChanged = (NodeType.IsDense(nodeTypes) && ChunkHasChange(nodeId, denseChunkMask)) || (NodeType.IsSparse(nodeTypes) && ChunkHasChange(nodeId, sparseChunkMask)); if (!chunkHasChanged) { nodeId += _chunkSize; continue; } ByteArray subArray = _array.at(nodeId); long subArrayLength = subArray.length(); for (int i = 0; i < subArrayLength && nodeId < _highNodeId; i++, nodeId++) { bool nodeHasChanged = (NodeType.IsDense(nodeTypes) && NodeIsChanged(subArray, nodeId, denseMask)) || (NodeType.IsSparse(nodeTypes) && NodeIsChanged(subArray, nodeId, sparseMask)); if (nodeHasChanged && NodeType.MatchesDense(nodeTypes, IsDense(_array, nodeId))) { visitor(nodeId, subArray); } } } }
//JAVA TO C# CONVERTER TODO TASK: Most Java annotations will not have direct .NET equivalent attributes: //ORIGINAL LINE: @Test public void shouldVisitChangedNodes() public virtual void ShouldVisitChangedNodes() { // GIVEN int nodes = 10; int typeId = 10; _cache = new NodeRelationshipCache(NumberArrayFactory.HEAP, 2, 100, Base); _cache.NodeCount = nodes; for (long nodeId = 0; nodeId < nodes; nodeId++) { _cache.incrementCount(nodeId); if (Random.nextBoolean()) { _cache.incrementCount(nodeId); } } MutableLongSet keySparseChanged = new LongHashSet(); MutableLongSet keyDenseChanged = new LongHashSet(); for (int i = 0; i < nodes / 2; i++) { long nodeId = Random.nextLong(nodes); _cache.getAndPutRelationship(nodeId, typeId, Direction.OUTGOING, Random.nextLong(1_000_000), false); bool dense = _cache.isDense(nodeId); (dense ? keyDenseChanged : keySparseChanged).add(nodeId); } { // WHEN (sparse) NodeChangeVisitor visitor = (nodeId, array) => { // THEN (sparse) assertTrue("Unexpected sparse change reported for " + nodeId, keySparseChanged.remove(nodeId)); }; _cache.visitChangedNodes(visitor, NodeType.NODE_TYPE_SPARSE); assertTrue("There was " + keySparseChanged.size() + " expected sparse changes that weren't reported", keySparseChanged.Empty); } { // WHEN (dense) NodeChangeVisitor visitor = (nodeId, array) => { // THEN (dense) assertTrue("Unexpected dense change reported for " + nodeId, keyDenseChanged.remove(nodeId)); }; _cache.visitChangedNodes(visitor, NodeType.NODE_TYPE_DENSE); assertTrue("There was " + keyDenseChanged.size() + " expected dense changes that weren reported", keyDenseChanged.Empty); } }