/**
* This file is part of d:swarm graph extension.
*
* d:swarm graph extension 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.
*
* d:swarm graph extension 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 d:swarm graph extension. If not, see <http://www.gnu.org/licenses/>.
*/
package org.dswarm.graph.index;
import java.util.concurrent.TimeUnit;
import org.neo4j.graphdb.GraphDatabaseService;
import org.neo4j.graphdb.Label;
import org.neo4j.graphdb.Transaction;
import org.neo4j.graphdb.schema.IndexCreator;
import org.neo4j.graphdb.schema.IndexDefinition;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.dswarm.graph.DMPGraphException;
import org.dswarm.graph.GraphProcessingStatics;
import org.dswarm.graph.model.GraphStatics;
/**
* @author tgaengler
*/
public class SchemaIndexUtils {
private static final Logger LOG = LoggerFactory.getLogger(SchemaIndexUtils.class);
public static void createSchemaIndices(final GraphDatabaseService database, final String databaseIdentifier) throws DMPGraphException {
getOrCreateSchemaIndex(GraphProcessingStatics.RESOURCE_LABEL, GraphStatics.URI_PROPERTY, database, databaseIdentifier);
getOrCreateSchemaIndex(GraphProcessingStatics.RESOURCE_LABEL, GraphStatics.HASH, database, databaseIdentifier);
getOrCreateSchemaIndex(GraphProcessingStatics.RESOURCE_TYPE_LABEL, GraphStatics.URI_PROPERTY, database, databaseIdentifier);
getOrCreateSchemaIndex(GraphProcessingStatics.LITERAL_LABEL, GraphStatics.VALUE_PROPERTY, database, databaseIdentifier);
getOrCreateSchemaIndex(GraphProcessingStatics.PREFIX_LABEL, GraphStatics.URI_PROPERTY, database, databaseIdentifier);
getOrCreateSchemaIndex(GraphProcessingStatics.PREFIX_LABEL, GraphProcessingStatics.PREFIX_PROPERTY, database, databaseIdentifier);
}
private static void getOrCreateSchemaIndex(final Label label, final String property, final GraphDatabaseService database, final String databaseIdentifier) throws DMPGraphException {
final IndexDefinition indexDefinition = SchemaIndexUtils.getOrCreateIndex(label, property, database, databaseIdentifier);
if (indexDefinition == null) {
throw new DMPGraphException(
String.format("something went wrong while index determination/creation for label '%s' and property '%s' at database '%s'", label.name(),
property, databaseIdentifier));
}
}
public static IndexDefinition getOrCreateIndex(final Label label, final String property, final GraphDatabaseService database, final String databaseIdentifier) {
LOG.debug("try to find index for label = '{}' and property = '{}' at database '{}'", label.name(), property, databaseIdentifier);
boolean notFound = false;
try (final Transaction tx = database.beginTx()) {
final Iterable<IndexDefinition> indices = database.schema().getIndexes(label);
IndexDefinition indexDefinition = null;
if (indices == null || !indices.iterator().hasNext()) {
tx.success();
tx.close();
notFound = true;
} else {
for (final IndexDefinition index : indices) {
notFound = false;
indexDefinition = index;
if (indexDefinition == null) {
tx.success();
tx.close();
notFound = true;
break;
}
final Iterable<String> propIter = indexDefinition.getPropertyKeys();
boolean propFound = false;
for(final String prop : propIter) {
if(prop.equals(property)) {
propFound = true;
break;
}
}
if(!propFound) {
notFound = true;
}
if(!notFound) {
break;
}
}
}
if (!notFound) {
LOG.debug("found existing index for label = '{}' and property = '{}' at database '{}'", label.name(), property, databaseIdentifier);
tx.success();
tx.close();
return indexDefinition;
}
} catch (final Exception e) {
LOG.error("sommething went wrong, while index determination for label '{}' and property '{}' at database '{}'", label, property, databaseIdentifier, e);
}
if (notFound) {
return createIndex(label, property, database, databaseIdentifier);
}
return null;
}
public static IndexDefinition createIndex(final Label label, final String property, final GraphDatabaseService database, final String databaseIdentifier) {
LOG.debug("try to create index for label = '{}' and property = '{}' at database '{}'", label.name(), property, databaseIdentifier);
final IndexDefinition indexDefinition;
try (final Transaction tx = database.beginTx()) {
final IndexCreator indexCreator = database.schema().indexFor(label).on(property);
indexDefinition = indexCreator.create();
LOG.debug("created index for label = '{}' and property = '{}' at database '{}'", label.name(), property, databaseIdentifier);
tx.success();
tx.close();
} catch (final Exception e) {
LOG.error("sommething went wrong, while index creation for label '{}' and property '{}' at database '{}'", label, property, databaseIdentifier, e);
return null;
}
return bringIndexOnline(label, property, database, databaseIdentifier, indexDefinition);
}
private static IndexDefinition bringIndexOnline(final Label label, final String property, final GraphDatabaseService database, final String databaseIdentifier,
final IndexDefinition indexDefinition) {
try (final Transaction tx = database.beginTx()) {
LOG.debug("try to bring index online for label = '{}' and property = '{}' at database '{}'", label.name(), property, databaseIdentifier);
database.schema().awaitIndexOnline(indexDefinition, 5, TimeUnit.SECONDS);
LOG.debug("brought index online for label = '{}' and property = '{}' at database '{}'", label.name(), property, databaseIdentifier);
tx.success();
tx.close();
return indexDefinition;
} catch (final Exception e) {
LOG.error("sommething went wrong, while bringing index online for label '{}' and property '{}' at database '{}'", label, property, databaseIdentifier, e);
return null;
}
}
}