private void check( Map<Node, Set<String>> expected, String change, Iterable<LabelEntry> changes ) { for ( LabelEntry entry : changes ) { Set<String> labels = expected.get(entry.node()); String message = String.format("':%s' should not be %s %s", entry.label().name(), change, entry.node() ); assertNotNull( message, labels ); assertTrue( message, labels.remove( entry.label().name() ) ); if ( labels.isEmpty() ) { expected.remove( entry.node() ); } } assertTrue(String.format("Expected more labels %s nodes: %s", change, expected), expected.isEmpty()); }
@Test public void showsDeletedNodes() throws Exception { // Given state.nodeDoDelete( 1L ); state.nodeDoDelete( 2L ); int labelId = 15; when( tokenRead.nodeLabelName( labelId ) ).thenReturn( "label" ); ops.withNode( 1, new long[]{labelId}, genericMap( "key", Values.of( "p" ) ) ); ops.withNode( 2, NO_LABELS ); // When & Then TxStateTransactionDataSnapshot snapshot = snapshot(); assertThat( idList( snapshot.deletedNodes() ), equalTo( asList( 1L, 2L ) ) ); assertThat( single( snapshot.removedLabels() ).label().name(), equalTo( "label" ) ); assertThat( single( snapshot.removedNodeProperties() ).key(), equalTo( "key" ) ); }
stream(data.assignedLabels()).filter( labelEntry -> !createdNodes.contains( labelEntry.node() ) ), (index, node, key, value, ignore) -> indexUpdate(state, aVoid -> { index.add(node, key, value); stream(data.removedLabels()).filter( labelEntry -> !data.isDeleted(labelEntry.node()) ), (index, node, key, value, ignore) -> indexUpdate(state, aVoid -> { index.remove(node, key); })); iterateNodeDeletions(stream(data.removedLabels()).filter( labelEntry -> data.isDeleted(labelEntry.node())), (nodeIndex, node, void1, void2, void3) -> indexUpdate(state, aVoid -> nodeIndex.remove(node))); return state;
private boolean hasLabel(LabelEntry labelEntry) { return indexLabels.contains(labelEntry.label().name()); }
private void check( Map<Node,Set<String>> expected, LabelEntry entry ) { Node node = entry.node(); String labelName = entry.label().name(); boolean hasEntity = expected.containsKey( node ); if ( !hasEntity && ignoreAdditionalData ) { return; } assertTrue( "Unexpected node " + node, hasEntity ); Set<String> labels = expected.get( node ); boolean hasLabel = labels.remove( labelName ); if ( !hasLabel && ignoreAdditionalData ) { return; } assertTrue( "Unexpected label " + labelName + " for " + node, hasLabel ); if ( labels.isEmpty() ) { expected.remove( node ); } }
@Test public void shouldListRemovedLabels() throws Exception { // Given int labelId = 2; when( tokenRead.nodeLabelName( labelId ) ).thenReturn( "theLabel" ); state.nodeDoRemoveLabel( labelId, 1L ); // When Iterable<LabelEntry> labelEntries = snapshot().removedLabels(); // Then LabelEntry entry = single( labelEntries ); assertThat( entry.label().name(), equalTo( "theLabel" ) ); assertThat( entry.node().getId(), equalTo( 1L ) ); }
@Test public void shouldListAddedLabels() throws Exception { // Given int labelId = 2; when( tokenRead.nodeLabelName( labelId ) ).thenReturn( "theLabel" ); state.nodeDoAddLabel( labelId, 1L ); // When Iterable<LabelEntry> labelEntries = snapshot().assignedLabels(); // Then LabelEntry entry = single( labelEntries ); assertThat( entry.label().name(), equalTo( "theLabel" ) ); assertThat( entry.node().getId(), equalTo( 1L ) ); }
private static Map<String,List<Node>> aggregateLabels(Iterable<LabelEntry> labelEntries) { if (!labelEntries.iterator().hasNext()) return Collections.emptyMap(); Map<String,List<Node>> result = new HashMap<>(); for (LabelEntry entry : labelEntries) { result.compute(entry.label().name(), (k, v) -> { if (v == null) v = new ArrayList<>(100); v.add(entry.node()); return v; }); } return result; }
private void iterateNodeDeletions(Stream<LabelEntry> stream, IndexFunction<Index<Node>, Node, Void, Void, Void> function) { stream.forEach(labelEntry -> { final Map<String, Collection<Index<Node>>> propertyIndicesMap = indexesByLabelAndProperty.get(labelEntry.label().name()); if (propertyIndicesMap!=null) { for (Collection<Index<Node>> indices: propertyIndicesMap.values()) { for (Index<Node> index: indices) { function.apply(index, labelEntry.node(), null, null, null); } } } }); }
private void iterateLabelChanges(Stream<LabelEntry> stream, IndexFunction<Index<Node>, Node, String, Object, Void> function) { stream.forEach(labelEntry -> { final String labelName = labelEntry.label().name(); final Map<String, Collection<Index<Node>>> propertyIndicesMap = indexesByLabelAndProperty.get(labelName); if (propertyIndicesMap != null) { final Node entity = labelEntry.node(); for (String key : entity.getPropertyKeys()) { Collection<Index<Node>> indices = propertyIndicesMap.get(key); if (indices != null) { for (Index<Node> index : indices) { Object value = entity.getProperty(key); String indexKey = labelName + "." + key; function.apply(index, entity, indexKey, value, null); } } } } }); }
Node node = labelEntry.node(); assignedLabels.get(node.getId()).add(labelEntry.label()); Node node = labelEntry.node(); deletedNodeLabels.put(node.getId(), new HashSet<Label>()); deletedNodeLabels.get(node.getId()).add(labelEntry.label()); continue; removedLabels.put(node.getId(), new HashSet<Label>()); removedLabels.get(node.getId()).add(labelEntry.label());
@Override public Collection<BulkableAction> beforeCommit(TransactionData transactionData) throws Exception { Map<IndexId, BulkableAction> actions = new HashMap<>(1000); for (Node node : transactionData.createdNodes()) { if (hasLabel(node)) actions.putAll(indexRequests(node)); } for (LabelEntry labelEntry : transactionData.assignedLabels()) { if (hasLabel(labelEntry)) { if (transactionData.isDeleted(labelEntry.node())) { actions.putAll(deleteRequests(labelEntry.node())); } else { actions.putAll(indexRequests(labelEntry.node())); } } } for (LabelEntry labelEntry : transactionData.removedLabels()) { if (hasLabel(labelEntry)) actions.putAll(deleteRequests(labelEntry.node(), labelEntry.label())); } for (PropertyEntry<Node> propEntry : transactionData.assignedNodeProperties()) { if (hasLabel(propEntry)) actions.putAll(indexRequests(propEntry.entity())); } for (PropertyEntry<Node> propEntry : transactionData.removedNodeProperties()) { if (!transactionData.isDeleted(propEntry.entity()) && hasLabel(propEntry)) actions.putAll(updateRequests(propEntry.entity())); } return actions.isEmpty() ? Collections.<BulkableAction>emptyList() : actions.values(); }