| //// |
| 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. |
| |
| |
| ******************************************************************************* |
| * The following groovy script generates the data samples for Gryo and is used |
| * when older versions of TinkerPop need data generation for the tests, |
| * specifically, the 3.2.x line before gremlin-io-test was a module. |
| ******************************************************************************* |
| import org.apache.tinkerpop.shaded.kryo.io.Output |
| import org.apache.tinkerpop.gremlin.tinkergraph.structure.* |
| import org.apache.tinkerpop.gremlin.structure.* |
| import org.apache.tinkerpop.gremlin.structure.io.gryo.* |
| import org.apache.tinkerpop.gremlin.structure.io.* |
| import org.apache.commons.configuration.BaseConfiguration |
| import java.time.* |
| |
| new File("io-output/dev-docs/").mkdirs() |
| new File("io-output/test-case-data/gryo").mkdirs() |
| |
| conf = new BaseConfiguration() |
| conf.setProperty(TinkerGraph.GREMLIN_TINKERGRAPH_DEFAULT_VERTEX_PROPERTY_CARDINALITY, VertexProperty.Cardinality.list.name()) |
| graph = TinkerGraph.open(conf) |
| TinkerFactory.generateTheCrew(graph) |
| g = graph.traversal() |
| |
| toGryo = { o, type, mapper, suffix = "" -> |
| def fileToWriteTo = new File("io-output/test-case-data/gryo/" + type.toLowerCase().replace(" ","") + "-" + suffix + ".kryo") |
| if (fileToWriteTo.exists()) fileToWriteTo.delete() |
| out = new Output(new FileOutputStream(fileToWriteTo)) |
| mapper.writeObject(out, o) |
| out.close() |
| } |
| |
| mapper = GryoMapper.build(). |
| version(GryoVersion.V1_0). |
| addRegistry(TinkerIoRegistryV2d0.instance()). |
| create().createMapper() |
| |
| toGryo(File, "Class", mapper, "v1d0") |
| toGryo(new Date(1481750076295L), "Date", mapper, "v1d0") |
| toGryo(100.00d, "Double", mapper, "v1d0") |
| toGryo(100.00f, "Float", mapper, "v1d0") |
| toGryo(100, "Integer", mapper, "v1d0") |
| toGryo(100L, "Long", mapper, "v1d0") |
| toGryo(new java.sql.Timestamp(1481750076295L), "Timestamp", mapper, "v1d0") |
| toGryo(UUID.fromString("41d2e28a-20a4-4ab0-b379-d810dede3786"), "UUID", mapper, "v1d0") |
| |
| toGryo(graph.edges().next(), "Edge", mapper, "v1d0") |
| toGryo(g.V().out().out().path().next(), "Path", mapper, "v1d0") |
| toGryo(graph.edges().next().properties().next(), "Property", mapper, "v1d0") |
| toGryo(new org.apache.tinkerpop.gremlin.structure.util.star.DirectionalStarGraph(org.apache.tinkerpop.gremlin.structure.util.star.StarGraph.of(graph.vertices().next()), Direction.BOTH).getStarGraphToSerialize(), "StarGraph", mapper, "v1d0") |
| toGryo(graph, "TinkerGraph", mapper, "v1d0") |
| toGryo(g.V(1).out().out().tree().next(), "Tree", mapper, "v1d0") |
| toGryo(graph.vertices().next(), "Vertex", mapper, "v1d0") |
| toGryo(graph.vertices().next().properties().next(), "VertexProperty", mapper, "v1d0") |
| |
| toGryo(SackFunctions.Barrier.normSack, "Barrier", mapper, "v1d0") |
| toGryo(new Bytecode.Binding("x", 1), "Binding", mapper, "v1d0") |
| toGryo(g.V().hasLabel('person').out().in().tree().asAdmin().getBytecode(), "Bytecode", mapper, "v1d0") |
| toGryo(VertexProperty.Cardinality.list, "Cardinality", mapper, "v1d0") |
| toGryo(Column.keys, "Column", mapper, "v1d0") |
| toGryo(Direction.OUT, "Direction", mapper, "v1d0") |
| toGryo(Operator.sum, "Operator", mapper, "v1d0") |
| toGryo(Order.shuffle, "Order", mapper, "v1d0") |
| toGryo(Pop.all, "Pop", mapper, "v1d0") |
| toGryo(org.apache.tinkerpop.gremlin.process.traversal.step.TraversalOptionParent.Pick.any, "Pick", mapper, "v1d0") |
| toGryo(org.apache.tinkerpop.gremlin.util.function.Lambda.function("{ it.get() }"), "Lambda", mapper, "v1d0") |
| tm = g.V().hasLabel('person').out().out().tree().profile().next() |
| metrics = new org.apache.tinkerpop.gremlin.process.traversal.util.MutableMetrics(tm.getMetrics(0)); |
| metrics.addNested(new org.apache.tinkerpop.gremlin.process.traversal.util.MutableMetrics(tm.getMetrics(1))); |
| toGryo(metrics, "Metrics", mapper, "v1d0") |
| toGryo(P.gt(0), "P", mapper, "v1d0") |
| toGryo(P.gt(0).and(P.lt(10)), "P and", mapper, "v1d0") |
| toGryo(P.gt(0).or(P.within(-1, -10, -100)), "P or", mapper, "v1d0") |
| toGryo(Scope.local, "Scope", mapper, "v1d0") |
| toGryo(T.label, "T", mapper, "v1d0") |
| toGryo(g.V().hasLabel('person').out().out().tree().profile().next(), "TraversalMetrics", mapper, "v1d0") |
| toGryo(g.V().hasLabel('person').nextTraverser(), "Traverser", mapper, "v1d0") |
| |
| toGryo(new java.math.BigDecimal(new java.math.BigInteger("123456789987654321123456789987654321")), "BigDecimal", mapper, "v1d0") |
| toGryo(new java.math.BigInteger("123456789987654321123456789987654321"), "BigInteger", mapper, "v1d0") |
| toGryo(new Byte("1"), "Byte", mapper, "v1d0") |
| toGryo(java.nio.ByteBuffer.wrap("some bytes for you".getBytes()), "ByteBuffer", mapper, "v1d0") |
| toGryo("x".charAt(0), "Char", mapper, "v1d0") |
| toGryo(Duration.ofDays(5), "Duration", mapper, "v1d0") |
| toGryo(java.net.InetAddress.getByName("localhost"), "InetAddress", mapper, "v1d0") |
| toGryo(Instant.parse("2016-12-14T16:39:19.349Z"), "Instant", mapper, "v1d0") |
| toGryo(LocalDate.of(2016, 1, 1), "LocalDate", mapper, "v1d0") |
| toGryo(LocalDateTime.of(2016, 1, 1, 12, 30), "LocalDateTime", mapper, "v1d0") |
| toGryo(LocalTime.of(12, 30, 45), "LocalTime", mapper, "v1d0") |
| toGryo(MonthDay.of(1, 1), "MonthDay", mapper, "v1d0") |
| toGryo(OffsetDateTime.parse("2007-12-03T10:15:30+01:00"), "OffsetDateTime", mapper, "v1d0") |
| toGryo(OffsetTime.parse("10:15:30+01:00"), "OffsetTime", mapper, "v1d0") |
| toGryo(Period.of(1, 6, 15), "Period", mapper, "v1d0") |
| toGryo(new Short("100"), "Short", mapper, "v1d0") |
| toGryo(Year.of(2016), "Year", mapper, "v1d0") |
| toGryo(YearMonth.of(2016, 6), "YearMonth", mapper, "v1d0") |
| toGryo(ZonedDateTime.of(2016, 12, 23, 12, 12, 24, 36, ZoneId.of("GMT+2")), "ZonedDateTime", mapper, "v1d0") |
| toGryo(ZoneOffset.ofHoursMinutesSeconds(3, 6, 9), "ZoneOffset", mapper, "v1d0") |
| ******************************************************************************* |
| //// |
| [[gryo]] |
| = Gryo |
| |
| image:gremlin-kryo.png[width=400,float=left] Gryo uses the popular link:https://github.com/EsotericSoftware/kryo[Kryo] |
| library to handle binary serialization for the JVM. There currently aren't any Kryo implementations in other languages |
| so the binding of this format to the JVM is a bit of a limitation, but if building a system on the JVM the use of |
| Gryo over other serialization format should yield smaller data sizes than other formats like GraphSON or GraphML, |
| improved serialization speed, as well as better support for the various Java data types that might not be supported |
| otherwise. |
| |
| Gryo is useful both as a "graph" serialization format and as a generalized serialization format that can read or |
| write any object. This characteristic makes it ideal for use in Gremlin Server, which is designed to return arbitrary |
| results of varying types. |
| |
| It is unlikely that Gryo users will try to consume or produce Gryo without using TinkerPop and Kryo classes to help do |
| it. Attempting to read or write a byte stream of Gryo without those tools would be challenging, so the depths of |
| what the Gryo format looks like in a byte-by-byte perspective will not be discussed here. It is enough to know that |
| TinkerPop has Kryo-based serializers for certain classes that it supports and that the bytes written or read must be |
| Kryo compliant. |
| |
| One of the key aspects of Gryo is that, by default, it requires that all types expected to be used to be registered |
| with the `GryoMapper`. There are two ways to do that: |
| |
| * On the `GryoMapper.Builder`, use the `addCustom` methods. These methods allow registration of single classes with |
| an optional custom serializer. |
| * Add a custom `IoRegistry` implementation with the `addRegistry` method on `GryoMapper.Builder`. The `IoRegistry` |
| contains registrations that will be supplied to the `GryoMapper`. There is additional documentation on how this works |
| in the link:https://tinkerpop.apache.org/docs/current/dev/provider/#io-implementations[provider documentation]. |
| |
| When using `addCustom` or `addRegistry`, it is important to remember that the order in which those methods are called |
| is important. The registrations get numeric "registration ids" and their order must match if the the Gryo is expected |
| to be compatible. Calls to `addCustom` will be applied first, prior to calls to `addRegistry` (which internally call |
| `addCustom`). |
| |
| It is possible to disable registration by setting `registrationRequired` on the `GryoMapper.Builder` to `false`, but |
| Gryo is less efficient with this feature is turned off. |
| |
| Until TinkerPop 3.3.0 there has only been one version of Gryo in 1.0 and the format for that version has generally |
| expanded as new releases of TinkerPop have been produced. "Expansion" has generally meant that new types have come to |
| be supported over time. The addition of new types means that while Gryo has remained at 1.0, older releases that |
| produced Gryo files will not be compatible with newer TinkerPop releases if the newer types are utilized. On the flip |
| side, newer release of TinkerPop are fully backward compatible with Gryo produced on older versions of TinkerPop. |
| |
| As of TinkerPop 3.3.0, there is now a new version of Gryo in 3.0 that is only partially compatible with 1.0. Attempts |
| to use 3.0 serializers with 1.0 serializers will likely lead to failure. |
| |
| Both versions of Gryo support all the types defined by GraphSON as well as others that are bound more specifically |
| to the JVM. The link:https://github.com/apache/tinkerpop/blob/x.y.z/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/structure/io/gryo/GryoVersion.java[GryoVersion] |
| class contains a listing of all the default registered classes. |