diff --git a/gremlin/src/main/java/org/apache/tinkerpop/gremlin/arcadedb/structure/ArcadeGraph.java b/gremlin/src/main/java/org/apache/tinkerpop/gremlin/arcadedb/structure/ArcadeGraph.java index b27e1ea027..525f5b28f1 100644 --- a/gremlin/src/main/java/org/apache/tinkerpop/gremlin/arcadedb/structure/ArcadeGraph.java +++ b/gremlin/src/main/java/org/apache/tinkerpop/gremlin/arcadedb/structure/ArcadeGraph.java @@ -61,12 +61,11 @@ public class ArcadeGraph implements Graph, Closeable { //private final ArcadeVariableFeatures graphVariables = new ArcadeVariableFeatures(); - private final ArcadeGraphTransaction transaction; - protected final Database database; - protected final BaseConfiguration configuration = new BaseConfiguration(); - - private final static Iterator EMPTY_VERTICES = Collections.emptyIterator(); - private final static Iterator EMPTY_EDGES = Collections.emptyIterator(); + private final ArcadeGraphTransaction transaction; + protected final Database database; + protected final BaseConfiguration configuration = new BaseConfiguration(); + private final static Iterator EMPTY_VERTICES = Collections.emptyIterator(); + private final static Iterator EMPTY_EDGES = Collections.emptyIterator(); static { TraversalStrategies.GlobalCache.registerStrategies(ArcadeGraph.class, TraversalStrategies.GlobalCache.getStrategies(Graph.class).clone()// @@ -82,12 +81,17 @@ public class ArcadeGraph implements Graph, Closeable { protected ArcadeGraph(final Configuration configuration) { this.configuration.copy(configuration); final String directory = this.configuration.getString(CONFIG_DIRECTORY); - final DatabaseFactory factory = new DatabaseFactory(directory); - if (!factory.exists()) - this.database = factory.create(); - else - this.database = factory.open(); + Database db = DatabaseFactory.getActiveDatabaseInstance(directory); + if (db == null) { + final DatabaseFactory factory = new DatabaseFactory(directory); + if (!factory.exists()) + db = factory.create(); + else + db = factory.open(); + } + + this.database = db; this.transaction = new ArcadeGraphTransaction(this); init(); diff --git a/gremlin/src/main/java/org/apache/tinkerpop/gremlin/arcadedb/structure/io/ArcadeIoRegistry.java b/gremlin/src/main/java/org/apache/tinkerpop/gremlin/arcadedb/structure/io/ArcadeIoRegistry.java index 8773e04c76..3810b6f637 100755 --- a/gremlin/src/main/java/org/apache/tinkerpop/gremlin/arcadedb/structure/io/ArcadeIoRegistry.java +++ b/gremlin/src/main/java/org/apache/tinkerpop/gremlin/arcadedb/structure/io/ArcadeIoRegistry.java @@ -17,9 +17,11 @@ import com.arcadedb.database.Database; import com.arcadedb.database.RID; +import org.apache.tinkerpop.gremlin.arcadedb.structure.io.binary.RIDBinarySerializer; import org.apache.tinkerpop.gremlin.arcadedb.structure.io.graphson.ArcadeGraphSONV3; import org.apache.tinkerpop.gremlin.arcadedb.structure.io.gryo.RIDGyroSerializer; import org.apache.tinkerpop.gremlin.structure.io.AbstractIoRegistry; +import org.apache.tinkerpop.gremlin.structure.io.binary.GraphBinaryIo; import org.apache.tinkerpop.gremlin.structure.io.graphson.GraphSONIo; import org.apache.tinkerpop.gremlin.structure.io.gryo.GryoIo; @@ -34,15 +36,14 @@ public class ArcadeIoRegistry extends AbstractIoRegistry { private final Database database; public ArcadeIoRegistry() { - database = null; - register(GryoIo.class, RID.class, new RIDGyroSerializer()); - register(GraphSONIo.class, RID.class, new ArcadeGraphSONV3(null)); + this(null); } public ArcadeIoRegistry(final Database database) { this.database = database; register(GryoIo.class, RID.class, new RIDGyroSerializer()); register(GraphSONIo.class, RID.class, new ArcadeGraphSONV3(database)); + register(GraphBinaryIo.class, RID.class, new RIDBinarySerializer()); } public Database getDatabase() { diff --git a/gremlin/src/main/java/org/apache/tinkerpop/gremlin/arcadedb/structure/io/binary/RIDBinarySerializer.java b/gremlin/src/main/java/org/apache/tinkerpop/gremlin/arcadedb/structure/io/binary/RIDBinarySerializer.java new file mode 100644 index 0000000000..a35bb754d2 --- /dev/null +++ b/gremlin/src/main/java/org/apache/tinkerpop/gremlin/arcadedb/structure/io/binary/RIDBinarySerializer.java @@ -0,0 +1,64 @@ +/* + * Copyright © 2021-present Arcade Data Ltd (info@arcadedata.com) + * + * 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.apache.tinkerpop.gremlin.arcadedb.structure.io.binary; + +import com.arcadedb.database.RID; +import org.apache.tinkerpop.gremlin.structure.io.Buffer; +import org.apache.tinkerpop.gremlin.structure.io.binary.DataType; +import org.apache.tinkerpop.gremlin.structure.io.binary.GraphBinaryReader; +import org.apache.tinkerpop.gremlin.structure.io.binary.GraphBinaryWriter; +import org.apache.tinkerpop.gremlin.structure.io.binary.types.CustomTypeSerializer; + +import java.io.*; + +/** + * @author Luca Garulli (l.garulli@arcadedata.com) + */ +public class RIDBinarySerializer implements CustomTypeSerializer { + @Override + public String getTypeName() { + return RID.class.getTypeName(); + } + + @Override + public DataType getDataType() { + return DataType.CUSTOM; + } + + @Override + public Object read(final Buffer buffer, final GraphBinaryReader context) throws IOException { + return new RID(null, buffer.readInt(), buffer.readLong()); + } + + @Override + public Object readValue(final Buffer buffer, final GraphBinaryReader context, final boolean nullable) throws IOException { + return new RID(null, buffer.readInt(), buffer.readLong()); + } + + @Override + public void write(final Object value, final Buffer buffer, final GraphBinaryWriter context) throws IOException { + final RID rid = (RID) value; + buffer.writeInt(rid.getBucketId()); + buffer.writeLong(rid.getPosition()); + } + + @Override + public void writeValue(final Object value, final Buffer buffer, final GraphBinaryWriter context, final boolean nullable) throws IOException { + final RID rid = (RID) value; + buffer.writeInt(rid.getBucketId()); + buffer.writeLong(rid.getPosition()); + } +} diff --git a/server/src/test/java/com/arcadedb/server/gremlin/GremlinServerTest.java b/server/src/test/java/com/arcadedb/server/gremlin/GremlinServerTest.java new file mode 100644 index 0000000000..2605ae1dd9 --- /dev/null +++ b/server/src/test/java/com/arcadedb/server/gremlin/GremlinServerTest.java @@ -0,0 +1,90 @@ +/* + * Copyright © 2021-present Arcade Data Ltd (info@arcadedata.com) + * + * 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 com.arcadedb.server.gremlin; + +import com.arcadedb.GlobalConfiguration; +import com.arcadedb.server.BaseGraphServerTest; +import com.arcadedb.utility.FileUtils; +import org.apache.tinkerpop.gremlin.arcadedb.structure.io.ArcadeIoRegistry; +import org.apache.tinkerpop.gremlin.driver.Cluster; +import org.apache.tinkerpop.gremlin.driver.remote.DriverRemoteConnection; +import org.apache.tinkerpop.gremlin.driver.ser.GraphBinaryMessageSerializerV1; +import org.apache.tinkerpop.gremlin.process.traversal.AnonymousTraversalSource; +import org.apache.tinkerpop.gremlin.process.traversal.dsl.graph.GraphTraversalSource; +import org.apache.tinkerpop.gremlin.structure.io.binary.TypeSerializerRegistry; +import org.junit.jupiter.api.AfterEach; +import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.Test; + +import java.io.*; + +public class GremlinServerTest extends BaseGraphServerTest { + + @Test + public void getAllVertices() { + final GraphTraversalSource g = traversal(); + var vertices = g.V().limit(3).toList(); + Assertions.assertEquals(3, vertices.size()); + } + + @Override + protected boolean isPopulateDatabase() { + return true; + } + + @Override + public void setTestConfiguration() { + super.setTestConfiguration(); + + // COPY GREMLIN SERVER FILES BEFORE STARTING THE GREMLIN SERVER + new File("./target/config").mkdirs(); + + try { + FileUtils.writeFile(new File("./target/config/gremlin-server.yaml"), + FileUtils.readStreamAsString(getClass().getClassLoader().getResourceAsStream("gremlin-server.yaml"), "utf8")); + + FileUtils.writeFile(new File("./target/config/gremlin-server.properties"), + FileUtils.readStreamAsString(getClass().getClassLoader().getResourceAsStream("gremlin-server.properties"), "utf8")); + + FileUtils.writeFile(new File("./target/config/gremlin-server.groovy"), + FileUtils.readStreamAsString(getClass().getClassLoader().getResourceAsStream("gremlin-server.groovy"), "utf8")); + + GlobalConfiguration.SERVER_PLUGINS.setValue("GremlinServer:com.arcadedb.server.gremlin.GremlinServerPlugin"); + + } catch (IOException e) { + Assertions.fail(e); + } + } + + @AfterEach + @Override + public void endTest() { + GlobalConfiguration.SERVER_PLUGINS.setValue(""); + super.endTest(); + } + + private Cluster createCluster() { + final GraphBinaryMessageSerializerV1 serializer = new GraphBinaryMessageSerializerV1( + new TypeSerializerRegistry.Builder().addRegistry(new ArcadeIoRegistry())); + + return Cluster.build().enableSsl(false).addContactPoint("localhost").port(8182).credentials("root", DEFAULT_PASSWORD_FOR_TESTS).serializer(serializer) + .create(); + } + + private GraphTraversalSource traversal() { + return AnonymousTraversalSource.traversal().withRemote(DriverRemoteConnection.using(createCluster(), "graph")); + } +} diff --git a/server/src/test/resources/gremlin-server.groovy b/server/src/test/resources/gremlin-server.groovy new file mode 100644 index 0000000000..3292cbe209 --- /dev/null +++ b/server/src/test/resources/gremlin-server.groovy @@ -0,0 +1,17 @@ +import org.apache.tinkerpop.gremlin.server.util.LifeCycleHook + +def globals = [:] + +// defines a sample LifeCycleHook that prints some output to the Gremlin Server console. +// note that the name of the key in the "global" map is unimportant. +globals << [hook : [ + onStartUp: { ctx -> + ctx.logger.info("Executed once at startup of Gremlin Server.") + }, + onShutDown: { ctx -> + ctx.logger.info("Executed once at shutdown of Gremlin Server.") + } +] as LifeCycleHook] + +// define the default TraversalSource to bind queries to - this one will be named "g". +globals << [graph : graph.traversal()] diff --git a/server/src/test/resources/gremlin-server.properties b/server/src/test/resources/gremlin-server.properties new file mode 100644 index 0000000000..b28e780be1 --- /dev/null +++ b/server/src/test/resources/gremlin-server.properties @@ -0,0 +1,2 @@ +gremlin.graph=org.apache.tinkerpop.gremlin.arcadedb.structure.ArcadeGraph +gremlin.arcadedb.directory=./target/databases0/graph diff --git a/server/src/test/resources/gremlin-server.yaml b/server/src/test/resources/gremlin-server.yaml new file mode 100644 index 0000000000..27d1c1faaf --- /dev/null +++ b/server/src/test/resources/gremlin-server.yaml @@ -0,0 +1,20 @@ +host: 0.0.0.0 +graphs: + graph: ./target/config/gremlin-server.properties +scriptEngines: + gremlin-groovy: + plugins: + org.apache.tinkerpop.gremlin.server.jsr223.GremlinServerGremlinPlugin: {} + org.apache.tinkerpop.gremlin.jsr223.ImportGremlinPlugin: + classImports: + - java.lang.Math + methodImports: + - 'java.lang.Math#*' + org.apache.tinkerpop.gremlin.jsr223.ScriptFileGremlinPlugin: + files: + - ./target/config/gremlin-server.groovy +serializers: + - className: org.apache.tinkerpop.gremlin.driver.ser.GraphBinaryMessageSerializerV1 + config: + ioRegistries: + - org.apache.tinkerpop.gremlin.arcadedb.structure.io.ArcadeIoRegistry