<commit_before>/*
 * Copyright 2015 Apache Software Foundation.
 *
 * 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.
 */
// TODO: Change license to match RAMCloud
package org.ellitron.tinkerpop.gremlin.torc.structure;

import org.apache.tinkerpop.gremlin.process.computer.GraphComputer;

import org.apache.tinkerpop.gremlin.structure.Graph;
import org.apache.tinkerpop.gremlin.structure.Vertex;
import org.apache.tinkerpop.gremlin.structure.Edge;
import org.apache.tinkerpop.gremlin.structure.Transaction;
import org.apache.tinkerpop.gremlin.structure.VertexProperty;

import org.apache.tinkerpop.gremlin.structure.util.ElementHelper;
import org.apache.tinkerpop.gremlin.structure.util.StringFactory;

import edu.stanford.ramcloud.*;
import edu.stanford.ramcloud.transactions.*;
import edu.stanford.ramcloud.ClientException.*;
import java.math.BigInteger;
import java.nio.ByteBuffer;
import java.nio.ByteOrder;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.EnumSet;
import java.util.HashMap;

import org.apache.commons.configuration.Configuration;

import org.apache.log4j.Logger;

import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.UUID;
import org.apache.log4j.BasicConfigurator;
import org.apache.tinkerpop.gremlin.structure.Direction;
import org.apache.tinkerpop.gremlin.structure.Element;
import org.apache.tinkerpop.gremlin.structure.Property;
import org.apache.tinkerpop.gremlin.structure.T;
import org.apache.tinkerpop.gremlin.structure.util.AbstractTransaction;
import org.ellitron.tinkerpop.gremlin.torc.structure.util.TorcHelper;

/**
 * TODO: Write documentation - Bidirectional edges
 *
 *
 * @author <NAME> <<EMAIL>>
 *
 * TODO: Make TorcGraph thread safe. Currently every TorcGraph method that
 * performs reads or writes to the database uses a ThreadLocal
 * RAMCloudTransaction to isolate transactions from different threads. Each
 * ThreadLocal RAMCloudTransaction object, however, is constructed with a
 * reference to the same RAMCloud client object, which itself is not thread
 * safe. Therefore, TorcGraph, although using separate RAMCloudTransaction
 * objects for each thread, it not actually thread safe. To fix this problem,
 * each ThreadLocal RAMCloudTransaction object needs to be constructed with its
 * own RAMCloud client object.
 *
 * TODO: Implement way of handling objects that are larger than 1MB.
 */
@Graph.OptIn(Graph.OptIn.SUITE_STRUCTURE_STANDARD)
public final class TorcGraph implements Graph {

    private static final Logger logger = Logger.getLogger(TorcGraph.class);

    // Configuration keys.
    public static final String CONFIG_GRAPH_NAME = "gremlin.torc.graphName";
    public static final String CONFIG_COORD_LOCATOR = "gremlin.torc.coordinatorLocator";
    public static final String CONFIG_NUM_MASTER_SERVERS = "gremlin.torc.numMasterServers";
    public static final String CONFIG_LOG_LEVEL = "gremlin.torc.logLevel";

    // Constants.
    private static final String ID_TABLE_NAME = "idTable";
    private static final String VERTEX_TABLE_NAME = "vertexTable";
    private static final String EDGE_TABLE_NAME = "edgeTable";
    private static final int MAX_TX_RETRY_COUNT = 100;
    private static final int NUM_ID_COUNTERS = 16;

    // Normal private members.
    private final Configuration configuration;
    private final String coordinatorLocator;
    private final int totalMasterServers;
    private RAMCloud ramcloud;
    private long idTableId, vertexTableId, edgeTableId;
    private final String graphName;
    private final TorcGraphTransaction transaction = new TorcGraphTransaction();

    boolean initialized = false;

    private TorcGraph(final Configuration configuration) {
        this.configuration = configuration;

        graphName = configuration.getString(CONFIG_GRAPH_NAME);
        coordinatorLocator = configuration.getString(CONFIG_COORD_LOCATOR);
        totalMasterServers = configuration.getInt(CONFIG_NUM_MASTER_SERVERS);

        logger.debug(String.format("Constructing TorcGraph (%s,%s,%d)", graphName, coordinatorLocator, totalMasterServers));
    }

    public boolean isInitialized() {
        return initialized;
    }

    private void initialize() {
        try {
            ramcloud = new RAMCloud(coordinatorLocator);
        } catch (ClientException e) {
            System.out.println(e.toString());
            throw e;
        }

        idTableId = ramcloud.createTable(graphName + "_" + ID_TABLE_NAME, totalMasterServers);
        vertexTableId = ramcloud.createTable(graphName + "_" + VERTEX_TABLE_NAME, totalMasterServers);
        edgeTableId = ramcloud.createTable(graphName + "_" + EDGE_TABLE_NAME, totalMasterServers);

        initialized = true;

        logger.debug("Initialized");
    }

    public static TorcGraph open(final Configuration configuration) {
        return new TorcGraph(configuration);
    }

    @Override
    public Vertex addVertex(final Object... keyValues) {
        long startTimeNs = 0;
        if (logger.isDebugEnabled()) {
            startTimeNs = System.nanoTime();
        }

        if (!initialized) {
            initialize();
        }

        transaction.readWrite();
        RAMCloudTransaction tx = transaction.threadLocalTx.get();

        ElementHelper.legalPropertyKeyValueArray(keyValues);

        // Only values of type String supported, currently.
        for (int i = 0; i < keyValues.length; i = i + 2) {
            if (!(keyValues[i] instanceof T) && !(keyValues[i + 1] instanceof String)) {
                throw Property.Exceptions.dataTypeOfPropertyValueNotSupported(keyValues[i + 1]);
            }
        }

        Object idValue = ElementHelper.getIdValue(keyValues).orElse(null);
        final String label = ElementHelper.getLabelValue(keyValues).orElse(Vertex.DEFAULT_LABEL);

        UInt128 vertexId;
        if (idValue != null) {
            if (idValue instanceof Byte) {
                vertexId = new UInt128((Byte) idValue);
            } else if (idValue instanceof Short) {
                vertexId = new UInt128((Short) idValue);
            } else if (idValue instanceof Integer) {
                vertexId = new UInt128((Integer) idValue);
            } else if (idValue instanceof Long) {
                vertexId = new UInt128((Long) idValue);
            } else if (idValue instanceof String) {
                vertexId = new UInt128((String) idValue);
            } else if (idValue instanceof BigInteger) {
                vertexId = new UInt128((BigInteger) idValue);
            } else if (idValue instanceof UUID) {
                vertexId = new UInt128((UUID) idValue);
            } else if (idValue instanceof byte[]) {
                vertexId = new UInt128((byte[]) idValue);
            } else {
                throw Vertex.Exceptions.userSuppliedIdsOfThisTypeNotSupported();
            }

            // Check if a vertex with this ID already exists.
            try {
                tx.read(vertexTableId, TorcHelper.getVertexLabelKey(vertexId));
                throw Graph.Exceptions.vertexWithIdAlreadyExists(vertexId.toString());
            } catch (ObjectDoesntExistException e) {
                // Good!
            }
        } else {
            long id_counter = (long) (Math.random() * NUM_ID_COUNTERS);
            long id = ramcloud.incrementInt64(idTableId, Long.toString(id_counter).getBytes(), 1, null);
<commit_msg>Added UInt128 to list of supported user supplied IDs.<commit_after>/*
 * Copyright 2015 Apache Software Foundation.
 *
 * 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.
 */
// TODO: Change license to match RAMCloud
package org.ellitron.tinkerpop.gremlin.torc.structure;

import org.apache.tinkerpop.gremlin.process.computer.GraphComputer;

import org.apache.tinkerpop.gremlin.structure.Graph;
import org.apache.tinkerpop.gremlin.structure.Vertex;
import org.apache.tinkerpop.gremlin.structure.Edge;
import org.apache.tinkerpop.gremlin.structure.Transaction;
import org.apache.tinkerpop.gremlin.structure.VertexProperty;

import org.apache.tinkerpop.gremlin.structure.util.ElementHelper;
import org.apache.tinkerpop.gremlin.structure.util.StringFactory;

import edu.stanford.ramcloud.*;
import edu.stanford.ramcloud.transactions.*;
import edu.stanford.ramcloud.ClientException.*;
import java.math.BigInteger;
import java.nio.ByteBuffer;
import java.nio.ByteOrder;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.EnumSet;
import java.util.HashMap;

import org.apache.commons.configuration.Configuration;

import org.apache.log4j.Logger;

import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.UUID;
import org.apache.log4j.BasicConfigurator;
import org.apache.tinkerpop.gremlin.structure.Direction;
import org.apache.tinkerpop.gremlin.structure.Element;
import org.apache.tinkerpop.gremlin.structure.Property;
import org.apache.tinkerpop.gremlin.structure.T;
import org.apache.tinkerpop.gremlin.structure.util.AbstractTransaction;
import org.ellitron.tinkerpop.gremlin.torc.structure.util.TorcHelper;

/**
 * TODO: Write documentation - Bidirectional edges
 *
 *
 * @author <NAME> <<EMAIL>>
 *
 * TODO: Make TorcGraph thread safe. Currently every TorcGraph method that
 * performs reads or writes to the database uses a ThreadLocal
 * RAMCloudTransaction to isolate transactions from different threads. Each
 * ThreadLocal RAMCloudTransaction object, however, is constructed with a
 * reference to the same RAMCloud client object, which itself is not thread
 * safe. Therefore, TorcGraph, although using separate RAMCloudTransaction
 * objects for each thread, it not actually thread safe. To fix this problem,
 * each ThreadLocal RAMCloudTransaction object needs to be constructed with its
 * own RAMCloud client object.
 *
 * TODO: Implement way of handling objects that are larger than 1MB.
 */
@Graph.OptIn(Graph.OptIn.SUITE_STRUCTURE_STANDARD)
public final class TorcGraph implements Graph {

    private static final Logger logger = Logger.getLogger(TorcGraph.class);

    // Configuration keys.
    public static final String CONFIG_GRAPH_NAME = "gremlin.torc.graphName";
    public static final String CONFIG_COORD_LOCATOR = "gremlin.torc.coordinatorLocator";
    public static final String CONFIG_NUM_MASTER_SERVERS = "gremlin.torc.numMasterServers";
    public static final String CONFIG_LOG_LEVEL = "gremlin.torc.logLevel";

    // Constants.
    private static final String ID_TABLE_NAME = "idTable";
    private static final String VERTEX_TABLE_NAME = "vertexTable";
    private static final String EDGE_TABLE_NAME = "edgeTable";
    private static final int MAX_TX_RETRY_COUNT = 100;
    private static final int NUM_ID_COUNTERS = 16;

    // Normal private members.
    private final Configuration configuration;
    private final String coordinatorLocator;
    private final int totalMasterServers;
    private RAMCloud ramcloud;
    private long idTableId, vertexTableId, edgeTableId;
    private final String graphName;
    private final TorcGraphTransaction transaction = new TorcGraphTransaction();

    boolean initialized = false;

    private TorcGraph(final Configuration configuration) {
        this.configuration = configuration;

        graphName = configuration.getString(CONFIG_GRAPH_NAME);
        coordinatorLocator = configuration.getString(CONFIG_COORD_LOCATOR);
        totalMasterServers = configuration.getInt(CONFIG_NUM_MASTER_SERVERS);

        logger.debug(String.format("Constructing TorcGraph (%s,%s,%d)", graphName, coordinatorLocator, totalMasterServers));
    }

    public boolean isInitialized() {
        return initialized;
    }

    private void initialize() {
        try {
            ramcloud = new RAMCloud(coordinatorLocator);
        } catch (ClientException e) {
            System.out.println(e.toString());
            throw e;
        }

        idTableId = ramcloud.createTable(graphName + "_" + ID_TABLE_NAME, totalMasterServers);
        vertexTableId = ramcloud.createTable(graphName + "_" + VERTEX_TABLE_NAME, totalMasterServers);
        edgeTableId = ramcloud.createTable(graphName + "_" + EDGE_TABLE_NAME, totalMasterServers);

        initialized = true;

        logger.debug("Initialized");
    }

    public static TorcGraph open(final Configuration configuration) {
        return new TorcGraph(configuration);
    }

    @Override
    public Vertex addVertex(final Object... keyValues) {
        long startTimeNs = 0;
        if (logger.isDebugEnabled()) {
            startTimeNs = System.nanoTime();
        }

        if (!initialized) {
            initialize();
        }

        transaction.readWrite();
        RAMCloudTransaction tx = transaction.threadLocalTx.get();

        ElementHelper.legalPropertyKeyValueArray(keyValues);

        // Only values of type String supported, currently.
        for (int i = 0; i < keyValues.length; i = i + 2) {
            if (!(keyValues[i] instanceof T) && !(keyValues[i + 1] instanceof String)) {
                throw Property.Exceptions.dataTypeOfPropertyValueNotSupported(keyValues[i + 1]);
            }
        }

        Object idValue = ElementHelper.getIdValue(keyValues).orElse(null);
        final String label = ElementHelper.getLabelValue(keyValues).orElse(Vertex.DEFAULT_LABEL);

        UInt128 vertexId;
        if (idValue != null) {
            if (idValue instanceof Byte) {
                vertexId = new UInt128((Byte) idValue);
            } else if (idValue instanceof Short) {
                vertexId = new UInt128((Short) idValue);
            } else if (idValue instanceof Integer) {
                vertexId = new UInt128((Integer) idValue);
            } else if (idValue instanceof Long) {
                vertexId = new UInt128((Long) idValue);
            } else if (idValue instanceof String) {
                vertexId = new UInt128((String) idValue);
            } else if (idValue instanceof BigInteger) {
                vertexId = new UInt128((BigInteger) idValue);
            } else if (idValue instanceof UUID) {
                vertexId = new UInt128((UUID) idValue);
            } else if (idValue instanceof byte[]) {
                vertexId = new UInt128((byte[]) idValue);
            } else if (idValue instanceof UInt128) {
                vertexId = (UInt128) idValue;
            } else {
                throw Vertex.Exceptions.userSuppliedIdsOfThisTypeNotSupported();
            }

            // Check if a vertex with this ID already exists.
            try {
                tx.read(vertexTableId, TorcHelper.getVertexLabelKey(vertexId));
                throw Graph.Exceptions.vertexWithIdAlreadyExists(vertexId.toString());
            } catch (ObjectDoesntExistException e) {
                // Good!
            }
        } else {
            long id_counter = (long) (Math.random() * NUM_ID_COUNTERS);
            long id = ramcloud.incrementInt64(idTableId, Long.toString(id_counter).getBytes(), 1, null);

{'fraction_non_alphanumeric': 0.08743680958621981, 'fraction_numerical': 0.006927541658865381, 'mean_word_length': 3.2223978919631096, 'pattern_counts': {'":': 0, '<': 11, '<?xml version=': 0, '>': 9, 'https://': 0, 'lorem ipsum': 0, 'www.': 2, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '5327669', 'n_tokens_mistral': 4493, 'n_tokens_neox': 4268, 'n_words': 1190}