org.apache.tinkerpop.gremlin.process.computer.bulkloading.BulkLoaderVertexProgram Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of driver-cql-shaded Show documentation
Show all versions of driver-cql-shaded Show documentation
A Shaded CQL ActivityType driver for http://nosqlbench.io/
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
package org.apache.tinkerpop.gremlin.process.computer.bulkloading;
import org.apache.commons.configuration.BaseConfiguration;
import org.apache.commons.configuration.Configuration;
import org.apache.commons.configuration.ConfigurationException;
import org.apache.commons.configuration.ConfigurationUtils;
import org.apache.commons.configuration.PropertiesConfiguration;
import org.apache.tinkerpop.gremlin.process.computer.GraphComputer;
import org.apache.tinkerpop.gremlin.process.computer.Memory;
import org.apache.tinkerpop.gremlin.process.computer.MessageScope;
import org.apache.tinkerpop.gremlin.process.computer.Messenger;
import org.apache.tinkerpop.gremlin.process.computer.VertexComputeKey;
import org.apache.tinkerpop.gremlin.process.computer.VertexProgram;
import org.apache.tinkerpop.gremlin.process.computer.util.AbstractVertexProgramBuilder;
import org.apache.tinkerpop.gremlin.process.traversal.dsl.graph.GraphTraversalSource;
import org.apache.tinkerpop.gremlin.process.traversal.dsl.graph.__;
import org.apache.tinkerpop.gremlin.process.traversal.step.util.event.MutationListener;
import org.apache.tinkerpop.gremlin.process.traversal.strategy.decoration.EventStrategy;
import org.apache.tinkerpop.gremlin.structure.Direction;
import org.apache.tinkerpop.gremlin.structure.Edge;
import org.apache.tinkerpop.gremlin.structure.Graph;
import org.apache.tinkerpop.gremlin.structure.Property;
import org.apache.tinkerpop.gremlin.structure.Vertex;
import org.apache.tinkerpop.gremlin.structure.VertexProperty;
import org.apache.tinkerpop.gremlin.structure.util.GraphFactory;
import org.apache.tinkerpop.gremlin.structure.util.StringFactory;
import org.javatuples.Pair;
import org.javatuples.Tuple;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.Map;
import java.util.Set;
/**
* @author Daniel Kuppitz (http://gremlin.guru)
* @deprecated As of release 3.2.10, not directly replaced - consider graph provider specific bulk loading methods
*/
@Deprecated
public class BulkLoaderVertexProgram implements VertexProgram {
private static final Logger LOGGER = LoggerFactory.getLogger(BulkLoaderVertexProgram.class);
public static final String BULK_LOADER_VERTEX_PROGRAM_CFG_PREFIX = "gremlin.bulkLoaderVertexProgram";
public static final String BULK_LOADER_CLASS_CFG_KEY = String.join(".", BULK_LOADER_VERTEX_PROGRAM_CFG_PREFIX, "class");
public static final String BULK_LOADER_VERTEX_ID_CFG_KEY = String.join(".", BULK_LOADER_VERTEX_PROGRAM_CFG_PREFIX, "vertexIdProperty");
public static final String INTERMEDIATE_BATCH_SIZE_CFG_KEY = String.join(".", BULK_LOADER_VERTEX_PROGRAM_CFG_PREFIX, "intermediateBatchSize");
public static final String KEEP_ORIGINAL_IDS_CFG_KEY = String.join(".", BULK_LOADER_VERTEX_PROGRAM_CFG_PREFIX, "keepOriginalIds");
public static final String USER_SUPPLIED_IDS_CFG_KEY = String.join(".", BULK_LOADER_VERTEX_PROGRAM_CFG_PREFIX, "userSuppliedIds");
public static final String WRITE_GRAPH_CFG_KEY = String.join(".", BULK_LOADER_VERTEX_PROGRAM_CFG_PREFIX, "writeGraph");
public static final String DEFAULT_BULK_LOADER_VERTEX_ID = "bulkLoader.vertex.id";
private final MessageScope messageScope;
private final Set elementComputeKeys;
private Configuration configuration;
private BulkLoader bulkLoader;
private Graph graph;
private GraphTraversalSource g;
private long intermediateBatchSize;
private BulkLoadingListener listener;
private BulkLoaderVertexProgram() {
messageScope = MessageScope.Local.of(__::inE);
elementComputeKeys = new HashSet<>();
}
private BulkLoader createBulkLoader() {
final BulkLoader loader;
final Configuration config = configuration.subset(BULK_LOADER_VERTEX_PROGRAM_CFG_PREFIX);
if (config.containsKey("class")) {
final String className = config.getString("class");
try {
final Class> bulkLoaderClass = Class.forName(className);
loader = (BulkLoader) bulkLoaderClass.getConstructor().newInstance();
} catch (ClassNotFoundException e) {
LOGGER.error("Unable to find custom bulk loader class: {}", className);
throw new IllegalStateException(e);
} catch (Exception e) {
LOGGER.error("Unable to create an instance of the given bulk loader class: {}", className);
throw new IllegalStateException(e);
}
} else {
loader = new IncrementalBulkLoader();
}
loader.configure(configuration);
return loader;
}
/**
* Eventually commits the current transaction and closes the current graph instance. commit() will be called
* if close is set true, otherwise it will only be called if the intermediate batch size is set and reached.
*
* @param close Whether to close the current graph instance after calling commit() or not.
*/
private void commit(final boolean close) {
if (!close && (intermediateBatchSize == 0L || listener.mutations() < intermediateBatchSize))
return;
if (null != graph) {
if (graph.features().graph().supportsTransactions()) {
LOGGER.info("Committing transaction on Graph instance: {} [{} mutations]", graph, listener.mutations());
try {
graph.tx().commit();
LOGGER.debug("Committed transaction on Graph instance: {}", graph);
listener.resetCounter();
} catch (Exception e) {
LOGGER.error("Failed to commit transaction on Graph instance: {}", graph);
graph.tx().rollback();
listener.resetCounter();
throw e;
}
}
if (close) {
try {
graph.close();
LOGGER.info("Closed Graph instance: {}", graph);
graph = null;
} catch (Exception e) {
LOGGER.warn("Failed to close Graph instance", e);
}
}
}
}
@Override
public void setup(final Memory memory) {
}
@Override
public void loadState(final Graph graph, final Configuration config) {
configuration = new BaseConfiguration();
if (config != null) {
ConfigurationUtils.copy(config, configuration);
}
intermediateBatchSize = configuration.getLong(INTERMEDIATE_BATCH_SIZE_CFG_KEY, 0L);
elementComputeKeys.add(VertexComputeKey.of(DEFAULT_BULK_LOADER_VERTEX_ID, true));
bulkLoader = createBulkLoader();
}
@Override
public void storeState(final Configuration config) {
VertexProgram.super.storeState(config);
if (configuration != null) {
ConfigurationUtils.copy(configuration, config);
}
}
@Override
public void workerIterationStart(final Memory memory) {
if (null == graph) {
graph = GraphFactory.open(configuration.subset(WRITE_GRAPH_CFG_KEY));
LOGGER.info("Opened Graph instance: {}", graph);
try {
listener = new BulkLoadingListener();
g = graph.traversal().withStrategies(EventStrategy.build().addListener(listener).create());
} catch (Exception e) {
try {
graph.close();
} catch (Exception e2) {
LOGGER.warn("Failed to close Graph instance", e2);
}
throw e;
}
} else {
LOGGER.warn("Leaked Graph instance: {}", graph);
}
}
@Override
public void workerIterationEnd(final Memory memory) {
this.commit(true);
}
@Override
public void execute(final Vertex sourceVertex, final Messenger messenger, final Memory memory) {
try {
executeInternal(sourceVertex, messenger, memory);
} catch (Exception e) {
if (graph.features().graph().supportsTransactions()) {
graph.tx().rollback();
}
throw e;
}
}
private void executeInternal(final Vertex sourceVertex, final Messenger messenger, final Memory memory) {
if (memory.isInitialIteration()) {
this.listener.resetStats();
// get or create the vertex
final Vertex targetVertex = bulkLoader.getOrCreateVertex(sourceVertex, graph, g);
// write all the properties of the vertex to the newly created vertex
final Iterator> vpi = sourceVertex.properties();
if (this.listener.isNewVertex()) {
vpi.forEachRemaining(vp -> bulkLoader.createVertexProperty(vp, targetVertex, graph, g));
} else {
vpi.forEachRemaining(vp -> bulkLoader.getOrCreateVertexProperty(vp, targetVertex, graph, g));
}
this.commit(false);
if (!bulkLoader.useUserSuppliedIds()) {
// create an id pair and send it to all the vertex's incoming adjacent vertices
sourceVertex.property(DEFAULT_BULK_LOADER_VERTEX_ID, targetVertex.id());
messenger.sendMessage(messageScope, Pair.with(sourceVertex.id(), targetVertex.id()));
}
} else if (memory.getIteration() == 1) {
if (bulkLoader.useUserSuppliedIds()) {
final Vertex outV = bulkLoader.getVertex(sourceVertex, graph, g);
final boolean incremental = outV.edges(Direction.OUT).hasNext();
sourceVertex.edges(Direction.OUT).forEachRemaining(edge -> {
final Vertex inV = bulkLoader.getVertex(edge.inVertex(), graph, g);
if (incremental) {
bulkLoader.getOrCreateEdge(edge, outV, inV, graph, g);
} else {
bulkLoader.createEdge(edge, outV, inV, graph, g);
}
this.commit(false);
});
} else {
// create an id map and populate it with all the incoming messages
final Map
© 2015 - 2025 Weber Informatics LLC | Privacy Policy