
org.neo4j.index.impl.lucene.legacy.LuceneCommandApplier Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of neo4j-lucene-index Show documentation
Show all versions of neo4j-lucene-index Show documentation
Integration layer between Neo4j and Lucene, providing one possible implementation of the Index API.
/*
* Copyright (c) 2002-2016 "Neo Technology,"
* Network Engine for Objects in Lund AB [http://neotechnology.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.index.impl.lucene.legacy;
import java.io.IOException;
import java.util.HashMap;
import java.util.Map;
import org.neo4j.kernel.impl.api.TransactionApplier;
import org.neo4j.kernel.impl.index.IndexCommand;
import org.neo4j.kernel.impl.index.IndexCommand.AddNodeCommand;
import org.neo4j.kernel.impl.index.IndexCommand.AddRelationshipCommand;
import org.neo4j.kernel.impl.index.IndexCommand.CreateCommand;
import org.neo4j.kernel.impl.index.IndexCommand.DeleteCommand;
import org.neo4j.kernel.impl.index.IndexCommand.RemoveCommand;
import org.neo4j.kernel.impl.index.IndexDefineCommand;
import org.neo4j.kernel.impl.index.IndexEntityType;
import org.neo4j.kernel.spi.legacyindex.IndexImplementation;
import static org.neo4j.index.impl.lucene.legacy.EntityId.IdData;
import static org.neo4j.index.impl.lucene.legacy.EntityId.RelationshipData;
/**
* Applies changes from {@link IndexCommand commands} onto one or more indexes from the same
* {@link IndexImplementation provider}.
*/
public class LuceneCommandApplier extends TransactionApplier.Adapter
{
private final LuceneDataSource dataSource;
private final Map nodeContexts = new HashMap<>();
private final Map relationshipContexts = new HashMap<>();
private final boolean recovery;
private IndexDefineCommand definitions;
public LuceneCommandApplier( LuceneDataSource dataSource, boolean recovery )
{
this.dataSource = dataSource;
this.recovery = recovery;
}
@Override
public boolean visitIndexAddNodeCommand( AddNodeCommand command ) throws IOException
{
IdData entityId = new IdData( command.getEntityId() );
return visitIndexAddCommand( command, entityId );
}
@Override
public boolean visitIndexAddRelationshipCommand( AddRelationshipCommand command ) throws IOException
{
RelationshipData entityId = new RelationshipData( command.getEntityId(), command.getStartNode(),
command.getEndNode() );
return visitIndexAddCommand( command, entityId );
}
private boolean visitIndexAddCommand( IndexCommand command, EntityId entityId )
{
CommitContext context = commitContext( command );
String key = definitions.getKey( command.getKeyId() );
Object value = command.getValue();
// Below is a check for a null value where such a value is ignored. This may look strange, but the
// reason is that there was this bug where adding a null value to an index would be fine and written
// into the log as a command, to later fail during application of that command, i.e. here.
// There was a fix introduced to throw IllegalArgumentException out to user right away if passing in
// null or object that had toString() produce null. Although databases already affected by this would
// not be able to recover, which is why this check is here.
if ( value != null )
{
context.ensureWriterInstantiated();
context.indexType.addToDocument( context.getDocument( entityId, true ).document, key, value );
}
return false;
}
@Override
public boolean visitIndexRemoveCommand( RemoveCommand command ) throws IOException
{
CommitContext context = commitContext( command );
String key = definitions.getKey( command.getKeyId() );
Object value = command.getValue();
context.ensureWriterInstantiated();
CommitContext.DocumentContext
document = context.getDocument( new IdData( command.getEntityId() ), false );
if ( document != null )
{
context.indexType.removeFromDocument( document.document, key, value );
}
return false;
}
@Override
public boolean visitIndexDeleteCommand( DeleteCommand command ) throws IOException
{
CommitContext context = commitContext( command );
context.documents.clear();
context.dataSource.deleteIndex( context.identifier, context.recovery );
return false;
}
@Override
public boolean visitIndexCreateCommand( CreateCommand createCommand ) throws IOException
{
return false;
}
@Override
public boolean visitIndexDefineCommand( IndexDefineCommand indexDefineCommand ) throws IOException
{
definitions = indexDefineCommand;
return false;
}
@Override
public void close()
{
try
{
if ( definitions != null )
{
dataSource.getWriteLock();
for ( CommitContext context : nodeContexts.values() )
{
context.close();
}
for ( CommitContext context : relationshipContexts.values() )
{
context.close();
}
}
}
catch ( IOException e )
{
throw new RuntimeException( "Failure to commit changes to lucene", e );
}
finally
{
if ( definitions != null )
{
dataSource.releaseWriteLock();
}
}
}
private CommitContext commitContext( IndexCommand command )
{
Map contextMap = commitContextMap( command.getEntityType() );
String indexName = definitions.getIndexName( command.getIndexNameId() );
CommitContext context = contextMap.get( indexName );
if ( context == null )
{
IndexIdentifier identifier =
new IndexIdentifier( IndexEntityType.byId( command.getEntityType() ), indexName );
// TODO the fact that we look up index type from config here using the index store
// directly should be avoided. But how can we do it in, say recovery?
context = new CommitContext( dataSource, identifier,
dataSource.getType( identifier, recovery ), recovery );
contextMap.put( indexName, context );
}
return context;
}
private Map commitContextMap( byte entityType )
{
if ( entityType == IndexEntityType.Node.id() )
{
return nodeContexts;
}
if ( entityType == IndexEntityType.Relationship.id() )
{
return relationshipContexts;
}
throw new IllegalArgumentException( "Unknown entity type " + entityType );
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy