// Copyright 2017 JanusGraph Authors
//
// Licensed 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.janusgraph.graphdb.transaction;
import static org.janusgraph.graphdb.configuration.GraphDatabaseConfiguration.ROOT_NS;
import java.time.Instant;
import com.google.common.base.Preconditions;
import org.janusgraph.core.schema.DefaultSchemaMaker;
import org.janusgraph.core.JanusGraphTransaction;
import org.janusgraph.core.TransactionBuilder;
import org.janusgraph.diskstorage.configuration.*;
import org.janusgraph.diskstorage.BaseTransactionConfig;
import org.janusgraph.diskstorage.util.StandardBaseTransactionConfig;
import org.janusgraph.graphdb.configuration.GraphDatabaseConfiguration;
import org.janusgraph.graphdb.database.StandardJanusGraph;
import org.janusgraph.diskstorage.util.time.TimestampProvider;
/**
* Used to configure a {@link org.janusgraph.core.JanusGraphTransaction}.
*
* @author Matthias Bröcheler (me@matthiasb.com);
* @see org.janusgraph.core.JanusGraphTransaction
*/
public class StandardTransactionBuilder implements TransactionConfiguration, TransactionBuilder {
private boolean isReadOnly = false;
private boolean hasEnabledBatchLoading = false;
private boolean assignIDsImmediately = false;
private boolean preloadedData = false;
private DefaultSchemaMaker defaultSchemaMaker;
private boolean verifyExternalVertexExistence = true;
private boolean verifyInternalVertexExistence = false;
private boolean verifyUniqueness = true;
private boolean acquireLocks = true;
private boolean propertyPrefetching = true;
private boolean singleThreaded = false;
private boolean threadBound = false;
private int vertexCacheSize;
private int dirtyVertexSize;
private long indexCacheWeight;
private String logIdentifier;
private int[] restrictedPartitions = new int[0];
private Instant userCommitTime = null;
private String groupName;
private final boolean forceIndexUsage;
private final ModifiableConfiguration writableCustomOptions;
private final Configuration customOptions;
private final StandardJanusGraph graph;
/**
* Constructs a new JanusGraphTransaction configuration with default configuration parameters.
*/
public StandardTransactionBuilder(GraphDatabaseConfiguration graphConfig, StandardJanusGraph graph) {
Preconditions.checkNotNull(graphConfig);
Preconditions.checkNotNull(graph);
if (graphConfig.isReadOnly()) readOnly();
if (graphConfig.isBatchLoading()) enableBatchLoading();
this.graph = graph;
this.defaultSchemaMaker = graphConfig.getDefaultSchemaMaker();
this.assignIDsImmediately = graphConfig.hasFlushIDs();
this.forceIndexUsage = graphConfig.hasForceIndexUsage();
this.groupName = graphConfig.getMetricsPrefix();
this.logIdentifier = null;
this.propertyPrefetching = graphConfig.hasPropertyPrefetching();
this.writableCustomOptions = GraphDatabaseConfiguration.buildGraphConfiguration();
this.customOptions = new MergedConfiguration(writableCustomOptions, graphConfig.getConfiguration());
vertexCacheSize(graphConfig.getTxVertexCacheSize());
dirtyVertexSize(graphConfig.getTxDirtyVertexSize());
}
public StandardTransactionBuilder(GraphDatabaseConfiguration graphConfig, StandardJanusGraph graph, Configuration customOptions) {
Preconditions.checkNotNull(graphConfig);
Preconditions.checkNotNull(graph);
if (graphConfig.isReadOnly()) readOnly();
if (graphConfig.isBatchLoading()) enableBatchLoading();
this.graph = graph;
this.defaultSchemaMaker = graphConfig.getDefaultSchemaMaker();
this.assignIDsImmediately = graphConfig.hasFlushIDs();
this.forceIndexUsage = graphConfig.hasForceIndexUsage();
this.groupName = graphConfig.getMetricsPrefix();
this.logIdentifier = null;
this.propertyPrefetching = graphConfig.hasPropertyPrefetching();
this.writableCustomOptions = null;
this.customOptions = customOptions;
vertexCacheSize(graphConfig.getTxVertexCacheSize());
dirtyVertexSize(graphConfig.getTxDirtyVertexSize());
}
public StandardTransactionBuilder threadBound() {
this.threadBound = true;
this.singleThreaded = true;
return this;
}
@Override
public StandardTransactionBuilder readOnly() {
this.isReadOnly = true;
return this;
}
@Override
public StandardTransactionBuilder enableBatchLoading() {
hasEnabledBatchLoading = true;
checkExternalVertexExistence(false);
consistencyChecks(false);
return this;
}
@Override
public StandardTransactionBuilder disableBatchLoading() {
hasEnabledBatchLoading = false;
checkExternalVertexExistence(true);
consistencyChecks(true);
return this;
}
@Override
public StandardTransactionBuilder vertexCacheSize(int size) {
Preconditions.checkArgument(size >= 0);
this.vertexCacheSize = size;
this.indexCacheWeight = size / 2;
return this;
}
@Override
public TransactionBuilder dirtyVertexSize(int size) {
this.dirtyVertexSize = size;
return this;
}
@Override
public StandardTransactionBuilder checkInternalVertexExistence(boolean enabled) {
this.verifyInternalVertexExistence = enabled;
return this;
}
@Override
public StandardTransactionBuilder checkExternalVertexExistence(boolean enabled) {
this.verifyExternalVertexExistence = enabled;
return this;
}
@Override
public TransactionBuilder consistencyChecks(boolean enabled) {
this.verifyUniqueness = enabled;
this.acquireLocks = enabled;
return this;
}
@Override
public StandardTransactionBuilder commitTime(Instant timestampSinceEpoch) {
this.userCommitTime = timestampSinceEpoch;
return this;
}
@Override
public void setCommitTime(Instant time) {
throw new UnsupportedOperationException("Use setCommitTime(lnog,TimeUnit)");
}
@Override
public StandardTransactionBuilder groupName(String p) {
this.groupName = p;
return this;
}
@Override
public StandardTransactionBuilder logIdentifier(String logName) {
this.logIdentifier = logName;
return this;
}
@Override
public TransactionBuilder restrictedPartitions(int[] partitions) {
Preconditions.checkNotNull(partitions);
this.restrictedPartitions=partitions;
return this;
}
public TransactionBuilder setPreloadedData(boolean preloaded) {
this.preloadedData = preloaded;
return this;
}
@Override
public TransactionBuilder customOption(String k, Object v) {
if (null == writableCustomOptions)
throw new IllegalStateException("This builder was not constructed with setCustomOption support");
writableCustomOptions.set((ConfigOption<Object>)ConfigElement.parse(ROOT_NS, k).element, v);
return this;
}
@Override
public JanusGraphTransaction start() {
TransactionConfiguration immutable = new ImmutableTxCfg(isReadOnly, hasEnabledBatchLoading,
assignIDsImmediately, preloadedData, forceIndexUsage, verifyExternalVertexExistence,
verifyInternalVertexExistence, acquireLocks, verifyUniqueness,
propertyPrefetching, singleThreaded, threadBound, getTimestampProvider(), userCommitTime,
indexCacheWeight, getVertexCacheSize(), getDirtyVertexSize(),
logIdentifier, restrictedPartitions, groupName,
defaultSchemaMaker, customOptions);
return graph.newTransaction(immutable);
}
/* ##############################################
TransactionConfig
############################################## */
@Override
public final boolean isReadOnly() {
return isReadOnly;
}
@Override
public final boolean hasAssignIDsImmediately() {
return assignIDsImmediately;
}
@Override
public boolean hasPreloadedData() { return preloadedData; }
@Override
public final boolean hasForceIndexUsage() {
return forceIndexUsage;
}
@Override
public boolean hasEnabledBatchLoading() {
return hasEnabledBatchLoading;
}
@Override
public final boolean hasVerifyExternalVertexExistence() {
return verifyExternalVertexExistence;
}
@Override
public final boolean hasVerifyInternalVertexExistence() {
return verifyInternalVertexExistence;
}
@Override
public final boolean hasAcquireLocks() {
return acquireLocks;
}
@Override
public final DefaultSchemaMaker getAutoSchemaMaker() {
return defaultSchemaMaker;
}
@Override
public final boolean hasVerifyUniqueness() {
return verifyUniqueness;
}
public boolean hasPropertyPrefetching() {
return propertyPrefetching;
}
@Override
public final boolean isSingleThreaded() {
return singleThreaded;
}
@Override
public final boolean isThreadBound() {
return threadBound;
}
@Override
public final int getVertexCacheSize() {
return vertexCacheSize;
}
@Override
public final int getDirtyVertexSize() {
return dirtyVertexSize;
}
@Override
public final long getIndexCacheWeight() {
return indexCacheWeight;
}
@Override
public String getLogIdentifier() {
return logIdentifier;
}
@Override
public int[] getRestrictedPartitions() {
return restrictedPartitions;
}
@Override
public boolean hasRestrictedPartitions() {
return restrictedPartitions.length>0;
}
@Override
public String getGroupName() {
return groupName;
}
@Override
public boolean hasGroupName() {
return null != groupName;
}
@Override
public Instant getCommitTime() {
return userCommitTime;
}
@Override
public boolean hasCommitTime() {
return userCommitTime!=null;
}
@Override
public <V> V getCustomOption(ConfigOption<V> opt) {
return getCustomOptions().get(opt);
}
@Override
public Configuration getCustomOptions() {
return customOptions;
}
@Override
public TimestampProvider getTimestampProvider() {
return graph.getConfiguration().getTimestampProvider();
}
private static class ImmutableTxCfg implements TransactionConfiguration {
private final boolean isReadOnly;
private final boolean hasEnabledBatchLoading;
private final boolean hasAssignIDsImmediately;
private final boolean hasPreloadedData;
private final boolean hasForceIndexUsage;
private final boolean hasVerifyExternalVertexExistence;
private final boolean hasVerifyInternalVertexExistence;
private final boolean hasAcquireLocks;
private final boolean hasVerifyUniqueness;
private final boolean hasPropertyPrefetching;
private final boolean isSingleThreaded;
private final boolean isThreadBound;
private final long indexCacheWeight;
private final int vertexCacheSize;
private final int dirtyVertexSize;
private final String logIdentifier;
private final int[] restrictedPartitions;
private final DefaultSchemaMaker defaultSchemaMaker;
private final BaseTransactionConfig handleConfig;
public ImmutableTxCfg(boolean isReadOnly,
boolean hasEnabledBatchLoading,
boolean hasAssignIDsImmediately,
boolean hasPreloadedData,
boolean hasForceIndexUsage,
boolean hasVerifyExternalVertexExistence,
boolean hasVerifyInternalVertexExistence,
boolean hasAcquireLocks, boolean hasVerifyUniqueness,
boolean hasPropertyPrefetching, boolean isSingleThreaded,
boolean isThreadBound, TimestampProvider times, Instant commitTime,
long indexCacheWeight, int vertexCacheSize, int dirtyVertexSize, String logIdentifier,
int[] restrictedPartitions,
String groupName, DefaultSchemaMaker defaultSchemaMaker,
Configuration customOptions) {
this.isReadOnly = isReadOnly;
this.hasEnabledBatchLoading = hasEnabledBatchLoading;
this.hasAssignIDsImmediately = hasAssignIDsImmediately;
this.hasPreloadedData = hasPreloadedData;
this.hasForceIndexUsage = hasForceIndexUsage;
this.hasVerifyExternalVertexExistence = hasVerifyExternalVertexExistence;
this.hasVerifyInternalVertexExistence = hasVerifyInternalVertexExistence;
this.hasAcquireLocks = hasAcquireLocks;
this.hasVerifyUniqueness = hasVerifyUniqueness;
this.hasPropertyPrefetching = hasPropertyPrefetching;
this.isSingleThreaded = isSingleThreaded;
this.isThreadBound = isThreadBound;
this.indexCacheWeight = indexCacheWeight;
this.vertexCacheSize = vertexCacheSize;
this.dirtyVertexSize = dirtyVertexSize;
this.logIdentifier = logIdentifier;
this.restrictedPartitions=restrictedPartitions;
this.defaultSchemaMaker = defaultSchemaMaker;
this.handleConfig = new StandardBaseTransactionConfig.Builder()
.commitTime(commitTime)
.timestampProvider(times)
.groupName(groupName)
.customOptions(customOptions).build();
}
@Override
public boolean hasEnabledBatchLoading() {
return hasEnabledBatchLoading;
}
@Override
public boolean isReadOnly() {
return isReadOnly;
}
@Override
public boolean hasAssignIDsImmediately() {
return hasAssignIDsImmediately;
}
@Override
public boolean hasPreloadedData() {
return hasPreloadedData;
}
@Override
public final boolean hasForceIndexUsage() {
return hasForceIndexUsage;
}
@Override
public boolean hasVerifyExternalVertexExistence() {
return hasVerifyExternalVertexExistence;
}
@Override
public boolean hasVerifyInternalVertexExistence() {
return hasVerifyInternalVertexExistence;
}
@Override
public boolean hasAcquireLocks() {
return hasAcquireLocks;
}
@Override
public DefaultSchemaMaker getAutoSchemaMaker() {
return defaultSchemaMaker;
}
@Override
public boolean hasVerifyUniqueness() {
return hasVerifyUniqueness;
}
@Override
public boolean hasPropertyPrefetching() {
return hasPropertyPrefetching;
}
@Override
public boolean isSingleThreaded() {
return isSingleThreaded;
}
@Override
public boolean isThreadBound() {
return isThreadBound;
}
@Override
public int getVertexCacheSize() {
return vertexCacheSize;
}
@Override
public int getDirtyVertexSize() {
return dirtyVertexSize;
}
@Override
public long getIndexCacheWeight() {
return indexCacheWeight;
}
@Override
public String getLogIdentifier() {
return logIdentifier;
}
@Override
public int[] getRestrictedPartitions() {
return restrictedPartitions;
}
@Override
public boolean hasRestrictedPartitions() {
return restrictedPartitions.length>0;
}
@Override
public Instant getCommitTime() {
return handleConfig.getCommitTime();
}
@Override
public void setCommitTime(Instant time) {
handleConfig.setCommitTime(time);
}
@Override
public boolean hasCommitTime() {
return handleConfig.hasCommitTime();
}
@Override
public String getGroupName() {
return handleConfig.getGroupName();
}
@Override
public boolean hasGroupName() {
return handleConfig.hasGroupName();
}
@Override
public <V> V getCustomOption(ConfigOption<V> opt) {
return handleConfig.getCustomOption(opt);
}
@Override
public Configuration getCustomOptions() {
return handleConfig.getCustomOptions();
}
@Override
public TimestampProvider getTimestampProvider() {
return handleConfig.getTimestampProvider();
}
}
}