Skip to content

Version 1.7 of the documentation is no longer actively maintained. The site that you are currently viewing is an archived snapshot. For up-to-date documentation, see the latest version.

HugeGraph Plugin mechanism and plug-in extension process

Background

  1. HugeGraph is not only open source and open, but also simple and easy to use. General users can easily add plug-in extension functions without changing the source code.
  2. HugeGraph supports a variety of built-in storage backends, and also allows users to extend custom backends without changing the existing source code.
  3. HugeGraph supports full-text search. The full-text search function involves word segmentation in various languages. Currently, there are 8 built-in Chinese word breakers, and it also allows users to expand custom word breakers without changing the existing source code.

Scalable dimension

Currently, the plug-in method provides extensions in the following dimensions:

  • backend storage
  • serializer
  • Custom configuration items
  • tokenizer

Plug-in implementation mechanism

  1. HugeGraph provides a plug-in interface HugeGraphPlugin, which supports plug-in through the Java SPI mechanism
  2. HugeGraph provides four extension registration functions: registerOptions(), registerBackend(), registerSerializer(),registerAnalyzer()
  3. The plug-in implementer implements the corresponding Options, Backend, Serializer or Analyzer interface
  4. The plug-in implementer implements register()the method of the HugeGraphPlugin interface, registers the specific implementation class listed in the above point 3 in this method, and packs it into a jar package
  5. The plug-in user puts the jar package in the HugeGraph Server installation directory plugins, modifies the relevant configuration items to the plug-in custom value, and restarts to take effect

Plug-in implementation process example

1 Create a new maven project

1.1 Name the project name: hugegraph-plugin-demo
1.2 Add hugegraph-core Jar package dependencies

The details of maven pom.xml are as follows:

 1<?xml version="1.0" encoding="UTF-8"?>
 2
 3<project xmlns="http://maven.apache.org/POM/4.0.0"
 4         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
 5         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
 6
 7    <modelVersion>4.0.0</modelVersion>
 8    <groupId>org.apache.hugegraph</groupId>
 9    <artifactId>hugegraph-plugin-demo</artifactId>
10    <version>1.0.0</version>
11    <packaging>jar</packaging>
12
13    <name>hugegraph-plugin-demo</name>
14
15    <dependencies>
16        <dependency>
17            <groupId>org.apache.hugegraph</groupId>
18            <artifactId>hugegraph-core</artifactId>
19            <version>${project.version}</version>
20        </dependency>
21    </dependencies>
22</project>

2 Realize extended functions

2.1 Extending a custom backend
2.1.1 Implement the interface BackendStoreProvider
  • Realizable interfaces: org.apache.hugegraph.backend.store.BackendStoreProvider
  • Or inherit an abstract class:org.apache.hugegraph.backend.store.AbstractBackendStoreProvider

Take the RocksDB backend RocksDBStoreProvider as an example:

 1public class RocksDBStoreProvider extends AbstractBackendStoreProvider {
 2
 3    protected String database() {
 4        return this.graph().toLowerCase();
 5    }
 6
 7    @Override
 8    protected BackendStore newSchemaStore(String store) {
 9        return new RocksDBSchemaStore(this, this.database(), store);
10    }
11
12    @Override
13    protected BackendStore newGraphStore(String store) {
14        return new RocksDBGraphStore(this, this.database(), store);
15    }
16
17    @Override
18    public String type() {
19        return "rocksdb";
20    }
21
22    @Override
23    public String version() {
24        return "1.0";
25    }
26}
2.1.2 Implement interface BackendStore

The BackendStore interface is defined as follows:

 1public interface BackendStore {
 2    // Store name
 3    public String store();
 4
 5    // Database name
 6    public String database();
 7
 8    // Get the parent provider
 9    public BackendStoreProvider provider();
10
11    // Open/close database
12    public void open(HugeConfig config);
13    public void close();
14
15    // Initialize/clear database
16    public void init();
17    public void clear();
18
19    // Add/delete data
20    public void mutate(BackendMutation mutation);
21
22    // Query data
23    public Iterator<BackendEntry> query(Query query);
24
25    // Transaction
26    public void beginTx();
27    public void commitTx();
28    public void rollbackTx();
29
30    // Get metadata by key
31    public <R> R metadata(HugeType type, String meta, Object[] args);
32
33    // Backend features
34    public BackendFeatures features();
35
36    // Generate an id for a specific type
37    public Id nextId(HugeType type);
38}
2.1.3 Extending custom serializers

The serializer must inherit the abstract class: org.apache.hugegraph.backend.serializer.AbstractSerializer ( implements GraphSerializer, SchemaSerializer) The main interface is defined as follows:

 1public interface GraphSerializer {
 2    public BackendEntry writeVertex(HugeVertex vertex);
 3    public BackendEntry writeVertexProperty(HugeVertexProperty<?> prop);
 4    public HugeVertex readVertex(HugeGraph graph, BackendEntry entry);
 5    public BackendEntry writeEdge(HugeEdge edge);
 6    public BackendEntry writeEdgeProperty(HugeEdgeProperty<?> prop);
 7    public HugeEdge readEdge(HugeGraph graph, BackendEntry entry);
 8    public BackendEntry writeIndex(HugeIndex index);
 9    public HugeIndex readIndex(HugeGraph graph, ConditionQuery query, BackendEntry entry);
10    public BackendEntry writeId(HugeType type, Id id);
11    public Query writeQuery(Query query);
12}
13
14public interface SchemaSerializer {
15    public BackendEntry writeVertexLabel(VertexLabel vertexLabel);
16    public VertexLabel readVertexLabel(HugeGraph graph, BackendEntry entry);
17    public BackendEntry writeEdgeLabel(EdgeLabel edgeLabel);
18    public EdgeLabel readEdgeLabel(HugeGraph graph, BackendEntry entry);
19    public BackendEntry writePropertyKey(PropertyKey propertyKey);
20    public PropertyKey readPropertyKey(HugeGraph graph, BackendEntry entry);
21    public BackendEntry writeIndexLabel(IndexLabel indexLabel);
22    public IndexLabel readIndexLabel(HugeGraph graph, BackendEntry entry);
23}
2.1.4 Extend custom configuration items

When adding a custom backend, it may be necessary to add new configuration items. The implementation process mainly includes:

  • Add a configuration item container class and implement the interface org.apache.hugegraph.config.OptionHolder
  • Provide a singleton method public static OptionHolder instance(), and call the method when the object is initialized OptionHolder.registerOptions()
  • Add configuration item declaration, single-value configuration item type is ConfigOption, multi-value configuration item type is ConfigListOption

Take the RocksDB configuration item definition as an example:

 1public class RocksDBOptions extends OptionHolder {
 2
 3    private RocksDBOptions() {
 4        super();
 5    }
 6
 7    private static volatile RocksDBOptions instance;
 8
 9    public static synchronized RocksDBOptions instance() {
10        if (instance == null) {
11            instance = new RocksDBOptions();
12            instance.registerOptions();
13        }
14        return instance;
15    }
16
17    public static final ConfigOption<String> DATA_PATH =
18            new ConfigOption<>(
19                    "rocksdb.data_path",
20                    "The path for storing data of RocksDB.",
21                    disallowEmpty(),
22                    "rocksdb-data"
23            );
24
25    public static final ConfigOption<String> WAL_PATH =
26            new ConfigOption<>(
27                    "rocksdb.wal_path",
28                    "The path for storing WAL of RocksDB.",
29                    disallowEmpty(),
30                    "rocksdb-data"
31            );
32
33    public static final ConfigListOption<String> DATA_DISKS =
34            new ConfigListOption<>(
35                    "rocksdb.data_disks",
36                    false,
37                    "The optimized disks for storing data of RocksDB. " +
38                    "The format of each element: `STORE/TABLE: /path/to/disk`." +
39                    "Allowed keys are [graph/vertex, graph/edge_out, graph/edge_in, " +
40                    "graph/secondary_index, graph/range_index]",
41                    null,
42                    String.class,
43                    ImmutableList.of()
44            );
45}
2.2 Extend custom tokenizer

The tokenizer needs to implement the interface org.apache.hugegraph.analyzer.Analyzer, take implementing a SpaceAnalyzer space tokenizer as an example.

 1package org.apache.hugegraph.plugin;
 2
 3import java.util.Arrays;
 4import java.util.HashSet;
 5import java.util.Set;
 6
 7import org.apache.hugegraph.analyzer.Analyzer;
 8
 9public class SpaceAnalyzer implements Analyzer {
10
11    @Override
12    public Set<String> segment(String text) {
13        return new HashSet<>(Arrays.asList(text.split(" ")));
14    }
15}

3. Implement the plug-in interface and register it

The plug-in registration entry is HugeGraphPlugin.register(), the custom plug-in must implement this interface method, and register the extension items defined above inside it. The interface org.apache.hugegraph.plugin.HugeGraphPlugin is defined as follows:

 1public interface HugeGraphPlugin {
 2
 3    public String name();
 4
 5    public void register();
 6
 7    public String supportsMinVersion();
 8
 9    public String supportsMaxVersion();
10}

And HugeGraphPlugin provides 4 static methods for registering extensions:

  • registerOptions(String name, String classPath): register configuration items
  • registerBackend(String name, String classPath): register backend (BackendStoreProvider)
  • registerSerializer(String name, String classPath): register serializer
  • registerAnalyzer(String name, String classPath): register tokenizer

The following is an example of registering the SpaceAnalyzer tokenizer:

 1package org.apache.hugegraph.plugin;
 2
 3public class DemoPlugin implements HugeGraphPlugin {
 4
 5    @Override
 6    public String name() {
 7        return "demo";
 8    }
 9
10    @Override
11    public void register() {
12        HugeGraphPlugin.registerAnalyzer("demo", SpaceAnalyzer.class.getName());
13    }
14}

4. Configure SPI entry

  1. Make sure the services directory exists: hugegraph-plugin-demo/resources/META-INF/services
  2. Create a text file in the services directory: org.apache.hugegraph.plugin.HugeGraphPlugin
  3. The content of the file is as follows: org.apache.hugegraph.plugin.DemoPlugin

5. Make Jar package

Through maven packaging, execute the command in the project directory mvn package, and a Jar package file will be generated in the target directory. Copy the Jar package to the plugins directory when using it, and restart the service to take effect.