protected void doCollect( int doc ) throws IOException, KernelException, IndexEntryConflictException { Document document = reader.document( doc ); long nodeId = LuceneDocumentStructure.getNodeId( document ); Value value = accessor.getNodePropertyValue( nodeId, propertyKeyId ); duplicateCheckStrategy.checkForDuplicate( value, nodeId ); }
@Override protected void doCollect( int doc ) throws IOException, KernelException, IndexEntryConflictException { Document document = reader.document( doc ); long nodeId = LuceneDocumentStructure.getNodeId( document ); Value[] values = new Value[propertyKeyIds.length]; for ( int i = 0; i < values.length; i++ ) { values[i] = accessor.getNodePropertyValue( nodeId, propertyKeyIds[i] ); } duplicateCheckStrategy.checkForDuplicate( values, nodeId ); } }
Value value = accessor.getNodePropertyValue( nodeId, propertyKeyId ); if ( !predicate.acceptsValue( value ) )
@Test public void shouldNotRejectIndexCollisionsCausedByPrecisionLossAsDuplicates() throws Exception { // given populator = newPopulator(); // Given we have a collision in our index... addUpdate( populator, 1, 1000000000000000001L ); addUpdate( populator, 2, 2 ); addUpdate( populator, 3, 1000000000000000001L ); // ... but the actual data in the store does not collide when( nodePropertyAccessor.getNodePropertyValue( 1, PROPERTY_KEY_ID ) ).thenReturn( Values.of( 1000000000000000001L ) ); when( nodePropertyAccessor.getNodePropertyValue( 3, PROPERTY_KEY_ID ) ).thenReturn( Values.of( 1000000000000000002L ) ); // Then our verification should NOT fail: populator.verifyDeferredConstraints( nodePropertyAccessor ); }
private static void verifyConstraintOn( LongArrayList nodeIds, NodePropertyAccessor nodePropertyAccessor, StoreIndexDescriptor descriptor ) throws IndexEntryConflictException { MutableMap<Value,Long> points = Maps.mutable.empty(); MutableLongIterator iter = nodeIds.longIterator(); try { while ( iter.hasNext() ) { long id = iter.next(); Value value = nodePropertyAccessor.getNodePropertyValue( id, descriptor.schema().getPropertyId() ); Long other = points.getIfAbsentPut( value, id ); if ( other != id ) { throw new IndexEntryConflictException( other, id, value ); } } } catch ( EntityNotFoundException e ) { throw new RuntimeException( "Failed to validate uniqueness constraint", e ); } }
@Before public void setup() throws IOException, EntityNotFoundException { indexProvider = providerCreator.apply( this ); rules.fileSystem().mkdirs( indexProvider.directoryStructure().rootDirectory() ); populator = indexProvider.getPopulator( descriptor, samplingConfig ); when( nodePropertyAccessor.getNodePropertyValue( anyLong(), anyInt() ) ).thenThrow( UnsupportedOperationException.class ); prevAccessCheck = UnsafeUtil.exchangeNativeAccessCheckEnabled( false ); }
@Test public void shouldRejectDuplicateEntryAfterUsingPopulatingUpdater() throws Exception { // given populator = newPopulator(); String valueString = "value1"; IndexUpdater updater = populator.newPopulatingUpdater( nodePropertyAccessor ); updater.process( add( 1, schemaDescriptor, valueString ) ); addUpdate( populator, 2, valueString ); Value value = Values.of( valueString ); when( nodePropertyAccessor.getNodePropertyValue( 1, PROPERTY_KEY_ID ) ).thenReturn( value ); when( nodePropertyAccessor.getNodePropertyValue( 2, PROPERTY_KEY_ID ) ).thenReturn( value ); // when try { populator.verifyDeferredConstraints( nodePropertyAccessor ); fail( "should have thrown exception" ); } // then catch ( IndexEntryConflictException conflict ) { assertEquals( 1, conflict.getExistingNodeId() ); assertEquals( value, conflict.getSinglePropertyValue() ); assertEquals( 2, conflict.getAddedNodeId() ); } }
@Test public void shouldFailAtVerificationStageWithAlreadyIndexedNumberValue() throws Exception { // given populator = newPopulator(); addUpdate( populator, 1, 1 ); addUpdate( populator, 2, 2 ); addUpdate( populator, 3, 1 ); when( nodePropertyAccessor.getNodePropertyValue( 1, PROPERTY_KEY_ID ) ).thenReturn( Values.of( 1 ) ); when( nodePropertyAccessor.getNodePropertyValue( 3, PROPERTY_KEY_ID ) ).thenReturn( Values.of( 1 ) ); // when try { populator.verifyDeferredConstraints( nodePropertyAccessor ); fail( "should have thrown exception" ); } // then catch ( IndexEntryConflictException conflict ) { assertEquals( 1, conflict.getExistingNodeId() ); assertEquals( Values.of( 1 ), conflict.getSinglePropertyValue() ); assertEquals( 3, conflict.getAddedNodeId() ); } }
@Test public void shouldFailAtVerificationStageWithAlreadyIndexedStringValue() throws Exception { // given populator = newPopulator(); String value = "value1"; addUpdate( populator, 1, value ); addUpdate( populator, 2, "value2" ); addUpdate( populator, 3, value ); when( nodePropertyAccessor.getNodePropertyValue( 1, PROPERTY_KEY_ID ) ).thenReturn( Values.of( value ) ); when( nodePropertyAccessor.getNodePropertyValue( 3, PROPERTY_KEY_ID ) ).thenReturn( Values.of( value ) ); // when try { populator.verifyDeferredConstraints( nodePropertyAccessor ); fail( "should have thrown exception" ); } // then catch ( IndexEntryConflictException conflict ) { assertEquals( 1, conflict.getExistingNodeId() ); assertEquals( Values.of( value ), conflict.getSinglePropertyValue() ); assertEquals( 3, conflict.getAddedNodeId() ); } }
@Test public void shouldCheckAllCollisionsFromUpdaterClose() throws Exception { // given populator = newPopulator(); int iterations = 228; // This value has to be high enough to stress the EntrySet implementation for ( int nodeId = 0; nodeId < iterations; nodeId++ ) { addUpdate( populator, nodeId, 1 ); when( nodePropertyAccessor.getNodePropertyValue( nodeId, PROPERTY_KEY_ID ) ).thenReturn( Values.of( nodeId ) ); } // ... and the actual conflicting property: addUpdate( populator, iterations, 1 ); when( nodePropertyAccessor.getNodePropertyValue( iterations, PROPERTY_KEY_ID ) ).thenReturn( Values.of( 1 ) ); // This collision is real!!! // when try { populator.verifyDeferredConstraints( nodePropertyAccessor ); fail( "should have thrown exception" ); } // then catch ( IndexEntryConflictException conflict ) { assertEquals( 1, conflict.getExistingNodeId() ); assertEquals( Values.of( 1 ), conflict.getSinglePropertyValue() ); assertEquals( iterations, conflict.getAddedNodeId() ); } }
@Test public void shouldRejectDuplicateEntryWhenUsingPopulatingUpdater() throws Exception { // given populator = newPopulator(); addUpdate( populator, 1, "value1" ); addUpdate( populator, 2, "value2" ); Value value = Values.of( "value1" ); when( nodePropertyAccessor.getNodePropertyValue( 1, PROPERTY_KEY_ID ) ).thenReturn( value ); when( nodePropertyAccessor.getNodePropertyValue( 3, PROPERTY_KEY_ID ) ).thenReturn( value ); // when try { IndexUpdater updater = populator.newPopulatingUpdater( nodePropertyAccessor ); updater.process( add( 3, schemaDescriptor, "value1" ) ); updater.close(); fail( "should have thrown exception" ); } // then catch ( IndexEntryConflictException conflict ) { assertEquals( 1, conflict.getExistingNodeId() ); assertEquals( value, conflict.getSinglePropertyValue() ); assertEquals( 3, conflict.getAddedNodeId() ); } }
when( nodePropertyAccessor.getNodePropertyValue( nodeId, PROPERTY_KEY_ID ) ).thenReturn( Values.of( nodeId ) ); when( nodePropertyAccessor.getNodePropertyValue( iterations, PROPERTY_KEY_ID ) ).thenReturn( Values.of( 1 ) ); // This collision is real!!!
@Test public void shouldNotRejectDuplicateEntryOnSameNodeIdAfterUsingPopulatingUpdater() throws Exception { // given populator = newPopulator(); when( nodePropertyAccessor.getNodePropertyValue( 1, PROPERTY_KEY_ID ) ).thenReturn( Values.of( "value1" ) ); IndexUpdater updater = populator.newPopulatingUpdater( nodePropertyAccessor ); updater.process( add( 1, schemaDescriptor, "value1" ) ); updater.process( change( 1, schemaDescriptor, "value1", "value1" ) ); updater.close(); addUpdate( populator, 2, "value2" ); addUpdate( populator, 3, "value3" ); // when populator.verifyDeferredConstraints( nodePropertyAccessor ); populator.close( true ); // then assertEquals( asList( 1L ), getAllNodes( getDirectory(), "value1" ) ); assertEquals( asList( 2L ), getAllNodes( getDirectory(), "value2" ) ); assertEquals( asList( 3L ), getAllNodes( getDirectory(), "value3" ) ); }
Value value = accessor.getNodePropertyValue( nodeId, propertyKeyId ); if ( !predicate.acceptsValue( value ) )
private static void verifyConstraintOn( LongArrayList nodeIds, NodePropertyAccessor nodePropertyAccessor, StoreIndexDescriptor descriptor ) throws IndexEntryConflictException { MutableMap<Value,Long> points = Maps.mutable.empty(); MutableLongIterator iter = nodeIds.longIterator(); try { while ( iter.hasNext() ) { long id = iter.next(); Value value = nodePropertyAccessor.getNodePropertyValue( id, descriptor.schema().getPropertyId() ); Long other = points.getIfAbsentPut( value, id ); if ( other != id ) { throw new IndexEntryConflictException( other, id, value ); } } } catch ( EntityNotFoundException e ) { throw new RuntimeException( "Failed to validate uniqueness constraint", e ); } }