Compare commits

..

5 Commits

Author SHA1 Message Date
zhangyi51 c02ed7107c Commit index updates in batch
To avoid commit all together during rebuilding index,
especially for Cassandra backend, which has batch limit 65535

fixed: #144
implemented: #82

Change-Id: I88ff4bc878bc24122f0bb6ecf9964246a083b9ab
2018-10-30 16:53:32 +08:00
liningrui 15e9fc6008 Fix scylladb backend init-store failed
The exception is "Indexes are not supported yet"

Fix: #48

Change-Id: I5012e2684b7d95ded236207b441fc71d77851fe7
2018-09-20 12:05:37 +08:00
zhoney 849258c03e fix bug init-store failed due to datapath and walpath error for rocksdb backend
fix #22

Change-Id: Id86628f0073301a969d054d4e52b115ac9096c14
2018-08-29 01:36:34 -05:00
zhangyi51 2957ca5c5a Fix bug that tinkerpop test suite can't find filter in resource directory
fix #8

Change-Id: If0d046a6eaaa76cabbc368fae18ecc05231a5307
2018-08-17 08:09:55 -05:00
liningrui f57be87958 HugeGraph-1358: Release 0.7.4
Change-Id: I145d8bb3ce96fb125ef81fa0fa5098654319acee
2018-08-10 15:43:02 +08:00
2171 changed files with 49569 additions and 333678 deletions

View File

@ -1,60 +0,0 @@
#
# 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.
#
github:
features:
# Enable issue management
issues: true
# Enable wiki for documentation
wiki: true
# Enable projects for project management boards
projects: true
description: A graph database that supports more than 100+ billion data, high performance and scalability (Include OLTP Engine & REST-API & Backends)
homepage: https://hugegraph.apache.org
del_branch_on_merge: true
#labels:
enabled_merge_buttons:
merge: false
rebase: true
squash: true
protected_branches:
master:
required_status_checks:
# strict means "Require PR to be up-to-date before merging". (enable when branch unstable)
strict: false
# contexts are the names of checks that must pass (now only enable the basic check)
contexts:
- Analyze (java)
- CodeQL
- check-license
- build-server (memory, 11)
- build-commons (11)
required_pull_request_reviews:
dismiss_stale_reviews: true
require_code_owner_reviews: false
required_approving_review_count: 2
# refer https://cwiki.apache.org/confluence/display/INFRA/Git+-+.asf.yaml+features#Git.asf.yamlfeatures-Notificationsettingsforrepositories
notifications:
# use https://selfserve.apache.org to manage it
pullrequests_status: issues@hugegraph.apache.org
pullrequests_comment: issues@hugegraph.apache.org
pullrequests_bot_dependabot: issues@hugegraph.apache.org
issues: issues@hugegraph.apache.org
issues_status: dev@hugegraph.apache.org
issues_comment: issues@hugegraph.apache.org
discussions: dev@hugegraph.apache.org

View File

@ -1,99 +0,0 @@
#
# 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.
#
root = true
[*]
charset = utf-8
end_of_line = lf
insert_final_newline = true
max_line_length = 100
ij_wrap_on_typing = true
ij_visual_guides = 100
[*.{java,xml,py}]
indent_style = space
indent_size = 4
[*.{java,xml}]
# Ignore the IDEA unsupported warning & it works well (indeed)
continuation_indent_size = 8
[*.md]
max_line_length = off
[*.java]
ij_java_doc_add_p_tag_on_empty_lines = true
ij_java_doc_do_not_wrap_if_one_line = true
ij_java_annotation_parameter_wrap = normal
ij_java_align_multiline_annotation_parameters = true
ij_java_class_count_to_use_import_on_demand = 100
ij_java_names_count_to_use_import_on_demand = 100
ij_java_imports_layout = $*, |, java.**, |, javax.**, |, org.**, |, com.**, |, *
ij_java_line_comment_at_first_column = false
ij_java_align_multiline_chained_methods = true
ij_java_align_multiline_parameters_in_calls = true
ij_java_align_multiline_binary_operation = true
ij_java_align_multiline_assignment = true
ij_java_align_multiline_ternary_operation = true
ij_java_align_multiline_throws_list = true
ij_java_align_multiline_extends_list = true
ij_java_align_multiline_array_initializer_expression = true
ij_java_call_parameters_wrap = normal
ij_java_method_parameters_wrap = normal
ij_java_resource_list_wrap = normal
ij_java_extends_list_wrap = normal
ij_java_throws_list_wrap = normal
ij_java_method_call_chain_wrap = normal
ij_java_binary_operation_wrap = normal
ij_java_ternary_operation_wrap = normal
ij_java_for_statement_wrap = normal
ij_java_array_initializer_wrap = normal
ij_java_assignment_wrap = normal
ij_java_assert_statement_wrap = normal
ij_java_if_brace_force = if_multiline
ij_java_do_while_brace_force = always
ij_java_while_brace_force = if_multiline
ij_java_for_brace_force = if_multiline
ij_java_wrap_long_lines = true
ij_java_parameter_annotation_wrap = normal
ij_java_enum_constants_wrap = split_into_lines
ij_java_keep_blank_lines_in_declarations = 1
ij_java_keep_blank_lines_in_code = 1
ij_java_keep_blank_lines_between_package_declaration_and_header = 1
ij_java_keep_blank_lines_before_right_brace = 1
ij_java_blank_lines_around_class = 1
ij_java_blank_lines_after_class_header = 1
ij_smart_tabs = true
[*.xml]
max_line_length = 120
ij_visual_guides = 120
ij_xml_text_wrap = off
ij_xml_space_inside_empty_tag = true
[.yaml]
ij_yaml_spaces_within_braces = false
ij_yaml_spaces_within_brackets = false
[.properties]
ij_properties_keep_blank_lines = true

16
.gitattributes vendored
View File

@ -1,16 +0,0 @@
# ignored file when package to source.tgz
.gitattributes export-ignore
.gitignore export-ignore
.asf.yaml export-ignore
apache-release.sh export-ignore
.licenserc.yaml export-ignore
.editorconfig export-ignore
hugegraph-store/hg-store-dist/src/assembly/static/bin/libjemalloc.so export-ignore
hugegraph-store/hg-store-dist/src/assembly/static/bin/libjemalloc_aarch64.so export-ignore
# ignored directory
.github/ export-ignore
.idea/ export-ignore
install-dist/scripts/ export-ignore
hugegraph-commons/hugegraph-dist/ export-ignore
docker/ export-ignore

View File

@ -1,103 +0,0 @@
name: Bug report (反馈 Bug)
description: Create a bug report to help HugeGraph improve
title: '[Bug] describe the main problem'
labels:
- bug
body:
- type: markdown
attributes:
value: >-
### Note (特别注意) :
> 1. 请先**搜索**现有的[Issues](https://github.com/apache/hugegraph/issues) 与
[FAQ](https://hugegraph.apache.org/docs/guides/faq/) 中没有与您相同
/ 相关的问题 (请勿重复提交)
> 2. 我们需要尽可能**详细**的信息来**复现**问题, 越详细的信息 (包括**日志 / 截图 / 配置**等)
会**越快**被响应和处理
> 3. Issue 标题请保留原有分类标签 (例如:`[Bug]`), 长段描述请增加`空行`并使用`序号`标记, 保持排版清晰
> 4. 请在对应的模块提交 issue, 缺乏有效信息 / 长时间 (> 14 天) 没有回复的 issue 可能会被 **关闭**
(更新时会再开启)
- type: dropdown
attributes:
label: Bug Type (问题类型)
options:
- gremlin (结果不合预期)
- rest-api (结果不合预期)
- other exception / error (其他异常报错)
- server status (启动/运行异常)
- logic (逻辑设计问题)
- performance (性能下降)
- others (please edit later)
- type: checkboxes
attributes:
label: Before submit
options:
- label: '我已经确认现有的 [Issues](https://github.com/apache/hugegraph/issues) 与
[FAQ](https://hugegraph.apache.org/docs/guides/faq/) 中没有相同 / 重复问题 (I have confirmed
and searched that there are no similar problems in the historical issue and documents)'
required: true
- type: textarea
attributes:
label: Environment (环境信息)
description: |
> server version could get from [rest-api](https://hugegraph.apache.org/docs/clients/restful-api/) (http://localhost:8080/versions)
value: |
- Server Version: 1.0.0 (Apache Release Version)
- Backend: RocksDB x nodes, HDD or SSD
- OS: xx CPUs, xx G RAM, Ubuntu 2x.x / CentOS 7.x
- Data Size: xx vertices, xx edges <!-- (like 1000W 点, 9000W 边) -->
validations:
required: true
- type: textarea
attributes:
label: Expected & Actual behavior (期望与实际表现)
description: |
> we can refer [How to create a minimal reproducible Example](https://stackoverflow.com/help/minimal-reproducible-example) (如何提供最简的可复现用例)
> if possible, please provide **screenshots** / Pic or `GIF` (请提供清晰的截图, 动图录屏更佳)
placeholder: |
type the main problem here
```java
// Exception / Error info (尽可能详细的日志 + 完整异常栈)
```
validations:
required: true
- type: textarea
attributes:
label: Vertex/Edge example (问题点 / 边数据举例)
description: |
> 如果问题与具体的点 / 边数据相关, 请提供完整的`查询语句 + 返回 JSON 结果`
placeholder: |
// Query URL
GET http://localhost:8080/gremlin?gremlin=hugegraph.traversal().V('1:tom')
// JSON of Vertex / Edge
{
"vertex": { "id": "xxx" }
}
render: javascript
- type: textarea
attributes:
label: Schema [VertexLabel, EdgeLabel, IndexLabel] (元数据结构)
description: |
> 如果问题与具体的点类型 / 边类型 / 索引类型相关, 请提供完整的 `Schema 返回 JSON 结果`
placeholder: |
// Query URL
GET http://localhost:8080/graphs/hugegraph/schema/vertexlabels
// JSON of GraphSchema
{
"vertex": { "id": "xxx" }
}
render: javascript

View File

@ -1,10 +0,0 @@
blank_issues_enabled: false
# 设置提 issue 前的参考文档
contact_links:
- name: HugeGraph Server Doc (EN/CN)
url: https://hugegraph.apache.org/docs/quickstart/hugegraph-server/
about: Please search question here before opening a new issue
- name: HugeGraph API Doc (EN/CN)
url: https://hugegraph.apache.org/docs/clients/
about: Please search usage here before opening a new issue

View File

@ -1,15 +0,0 @@
name: Feature request (新需求 / 功能)
description: Give an idea for HugeGraph
title: '[Feature] describe the new feature'
labels:
- feature
body:
- type: textarea
attributes:
label: Feature Description (功能描述)
description: |
> 请简要描述新功能 / 需求的使用场景或上下文, 最好能给个具体的例子说明
placeholder: type the feature description here
validations:
required: true

View File

@ -1,103 +0,0 @@
name: Ask question (提问)
description: Question about usage or configs in HugeGraph
title: '[Question] describe your problem'
body:
- type: markdown
attributes:
value: >-
### Note (特别注意) :
> 1. 请先**搜索**现有的[Issues](https://github.com/apache/hugegraph/issues) 与
[FAQ](https://hugegraph.apache.org/docs/guides/faq/) 中没有与您相同
/ 相关的问题 (请勿重复提交)
> 2. 我们需要尽可能**详细**的信息来**复现**问题, 越详细的信息 (包括**日志 / 截图 / 配置**等)
会**越快**被响应和处理
> 3. Issue 标题请保留原有分类标签 (例如:`[Bug]`), 长段描述请增加`空行`并使用`序号`标记, 保持排版清晰
> 4. 请在对应的模块提交 issue, 缺乏有效信息 / 长时间 (> 14 天) 没有回复的 issue 可能会被 **关闭**
(更新时会再开启)
- type: dropdown
attributes:
label: Problem Type (问题类型)
options:
- gremlin (结果不合预期)
- rest-api (结果不合预期)
- server status (启动/运行异常)
- configs (配置项 / 文档相关)
- struct / logic (架构 / 逻辑设计问题)
- performance (性能优化)
- other exception / error (其他异常报错)
- others (please edit later)
- type: checkboxes
attributes:
label: Before submit
options:
- label: '我已经确认现有的 [Issues](https://github.com/apache/hugegraph/issues) 与
[FAQ](https://hugegraph.apache.org/docs/guides/faq/) 中没有相同 / 重复问题 (I have confirmed
and searched that there are no similar problems in the historical issue and documents)'
required: true
- type: textarea
attributes:
label: Environment (环境信息)
description: |
> server version could get from [rest-api](https://hugegraph.apache.org/docs/clients/restful-api/) (http://localhost:8080/versions)
value: |
- Server Version: 1.0.0 (Apache Release Version)
- Backend: RocksDB x nodes, HDD or SSD
- OS: xx CPUs, xx G RAM, Ubuntu 2x.x / CentOS 7.x
- Data Size: xx vertices, xx edges <!-- (like 1000W 点, 9000W 边) -->
validations:
required: true
- type: textarea
attributes:
label: Your Question (问题描述)
description: |
> 图使用 / 配置相关问题,请优先参考 [REST-API 文档](https://hugegraph.apache.org/docs/clients/restful-api/),
> 以及 [Server 配置文档](https://hugegraph.apache.org/docs/config/)
> if possible, please provide **screenshots** / Pic or `GIF` (请提供清晰的截图, 动图录屏更佳)
placeholder: |
type the main problem here
```java
// Exception / Error info (尽可能详细的日志 + 完整异常栈)
```
validations:
required: true
- type: textarea
attributes:
label: Vertex/Edge example (问题点 / 边数据举例)
description: |
> 如果问题与具体的点 / 边数据相关, 请提供完整的`查询语句 + 返回 JSON 结果`
placeholder: |
// Query URL
GET http://localhost:8080/gremlin?gremlin=hugegraph.traversal().V('1:tom')
// JSON of Vertex / Edge
{
"vertex": { "id": "xxx" }
}
render: javascript
- type: textarea
attributes:
label: Schema [VertexLabel, EdgeLabel, IndexLabel] (元数据结构)
description: |
> 如果问题与具体的点类型 / 边类型 / 索引类型相关, 请提供完整的 `Schema 返回 JSON 结果`
placeholder: |
// Query URL
GET http://localhost:8080/graphs/hugegraph/schema/vertexlabels
// JSON of GraphSchema
{
"vertex": { "id": "xxx" }
}
render: javascript

View File

@ -1,67 +0,0 @@
<!--
Thank you very much for contributing to Apache HugeGraph, we are happy that you want to help us improve it!
Here are some tips for you:
1. If this is your first time, please read the [contributing guidelines](https://github.com/apache/hugegraph/blob/master/CONTRIBUTING.md)
2. If a PR fix/close an issue, type the message "close xxx" (xxx is the link of related
issue) in the content, GitHub will auto link it (Required)
3. Name the PR title in "Google Commit Format", start with "feat | fix | perf | refactor | doc | chore",
such like: "feat(core): support the PageRank algorithm" or "fix: wrong break in the compute loop" (module is optional)
skip it if you are unsure about which is the best component.
4. One PR address one issue, better not to mix up multiple issues.
5. Put an `x` in the `[ ]` to mark the item as CHECKED. `[x]` (or click it directly after
published)
-->
## Purpose of the PR
- close #xxx <!-- or use "fix #xxx", "xxx" is the ID-link of related issue, e.g: close #1024 -->
<!--
Please explain more context in this section, clarify why the changes are needed.
e.g:
- If you propose a new API, clarify the use case for a new API.
- If you fix a bug, you can clarify why it is a bug, and should be associated with an issue.
-->
## Main Changes
<!-- Please clarify what changes you are proposing. The purpose of this section is to outline the changes and how this PR fixes the issue. These change logs are helpful for better and faster reviews.)
For example:
- If you introduce a new feature, please show detailed design here or add the link of design documentation.
- If you refactor some codes with changing classes, showing the class hierarchy will help reviewers.
- If there is a discussion in the mailing list, please add the link. -->
## Verifying these changes
<!-- Please pick the proper options below -->
- [ ] Trivial rework / code cleanup without any test coverage. (No Need)
- [ ] Already covered by existing tests, such as *(please modify tests here)*.
- [ ] Need tests and can be verified as follows:
- xxx
## Does this PR potentially affect the following parts?
<!-- DO NOT REMOVE THIS SECTION. CHECK THE PROPER BOX ONLY. -->
- [ ] Dependencies ([add/update license](https://hugegraph.apache.org/docs/contribution-guidelines/contribute/#321-check-licenses) info & [regenerate_dependencies](../hugegraph-server/hugegraph-dist/scripts/dependency/regenerate_known_dependencies.sh)) <!-- Don't forget to add/update the info in "LICENSE" & "NOTICE" files (both in root & dist module) -->
- [ ] Modify configurations
- [ ] The public API
- [ ] Other affects (typed here)
- [ ] Nope
## Documentation Status
<!-- DO NOT REMOVE THIS SECTION. CHECK THE PROPER BOX ONLY. -->
- [ ] `Doc - TODO` <!-- Your PR changes impact docs and you will update later -->
- [ ] `Doc - Done` <!-- Related docs have been already added or updated -->
- [ ] `Doc - No Need` <!-- Your PR changes don't impact/need docs -->

View File

@ -1,43 +0,0 @@
<settings xmlns="http://maven.apache.org/SETTINGS/1.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/SETTINGS/1.0.0 https://maven.apache.org/xsd/settings-1.0.0.xsd">
<servers>
<server>
<id>github</id>
<username>${env.GITHUB_ACTOR}</username>
<password>${env.GITHUB_TOKEN}</password>
</server>
</servers>
<profiles>
<profile>
<id>local-repo</id>
<repositories>
<repository>
<id>central</id>
<url>https://repo.maven.apache.org/maven2</url>
<releases>
<enabled>true</enabled>
</releases>
<snapshots>
<enabled>false</enabled>
</snapshots>
</repository>
<repository>
<id>staged-releases</id>
<url>https://repository.apache.org/content/groups/staging/</url>
</repository>
</repositories>
<pluginRepositories>
<pluginRepository>
<id>staged-releases</id>
<url>https://repository.apache.org/content/groups/staging/</url>
</pluginRepository>
</pluginRepositories>
</profile>
</profiles>
<activeProfiles>
<activeProfile>local-repo</activeProfile>
</activeProfiles>
</settings>

View File

@ -1,318 +0,0 @@
# [New Podling Proposal of HugeGraph](https://cwiki.apache.org/confluence/display/INCUBATOR/New+Podling+Proposal)
## Abstract
HugeGraph is a high-performance scalable graph database.
## Proposal
HugeGraph is a large-scale and easy-to-use graph database. In the cases of 100+ billion data (vertices and edges), HugeGraph has complete HTAP capabilities built into its internal system. The design goal of HugeGraph is to achieve a balance between availability, performance, and cost.
We believe that the HugeGraph project will benefit the open-source community if HugeGraph is introduced into the Apache Software Foundation.
### Background
HugeGraph graph database was initially developed at Baidu, the leading search engine company in China. HugeGraph was designed to solve the large-scale graph analysis requirements for the task of anti-fraud. Relational databases are usually at a disadvantage in dealing with relational analysis, due to slow join performance, especially in the case of a large-scale graph with multiple dimensions and deep association relationships. Graph databases are in general considered a good alternative in dealing with large-scale relational analysis.
### Rationale
Generally, most graph databases can only process up to 1-billion-scale graphs, but it lacks a system to process 100-billion-scale graphs. Some graph databases may only support online query (OLTP), and some graph platforms only support graph computing (OLAP). HugeGraph is designed to support both online query and graph computing in the scenarios of 100+ billion data.
### Initial Goals
Although most of the main development of HugeGraph has been completed, there are several areas that still need future development. Some areas we want to focus on in the Apache incubation stage include:
- Higher graph computing loading performance: the current architecture (especially the separation of computing and storage) brings greater flexibility and cost savings, but with some performance overhead, which needs to be improved.
- RocksDB-based sharding storage development, based on the affinity architecture of query and storage. Since RocksDB is known for its good performance, but currently HugeGraph only supports the raft-based replication mode, we plan to support scale-out and distributed atomic transactions for RocksDB-based storage.
- Parallel OLTP query: at present, HugeGraph can perform parallel OLAP graph-computing, but the OLTP query only supports parallel execution on a single machine. In certain scenarios, the OLTP query needs to be implemented in parallel on multiple machines.
- Higher-performance queries: such as supporting faster query optimization, parallel primitive collections, and fine-grained caching strategies.
- Better usability: more OLTP/OLAP algorithms, APIs and toolchains, rich UI, etc...
- More language clients: such as supporting Python and Go languages.
- Some other optimizations: such as supporting pre-sorting graph loading.
### Current Status
#### Meritocracy
HugeGraph was incubated at Baidu in 2016 and open-sourced on [GitHub](https://github.com/hugegraph/hugegraph) in 2018. The project (including sub-projects) now has 30+ contributors from many companies. Some of these contributors become committers, and the project has hundreds of known users around the world. We will follow Apache's Meritocracy way to re-organize the community roles. We have set up the PPMC Team and Committer Team. Of course, contributions are welcomed and highly valued. New contributors are guided and reviewed by existing PMC members. When an active contributor has submitted enough good patches, PMC will start a vote to promote him/her to become a member of the Committer Team or PMC Team.
#### Community
Baidu has been building a community around HugeGraph users and developers for the last 3 years, and now we make use of GitHub as code hosting and community communication. The most of core developers are from Baidu. Besides, there are 10+ contributors from other companies such as NetEase, 360, Iflytek, and Huya. We hope to grow the base of contributors by inviting all those who offer contributions through The Apache Way.
#### Core Developers
The core developers are all experienced open-source developers. They have operated the HugeGraph Community for 3 years, and they are contributors to Linux kernel, OpenStack, Ceph, RocksDB, Apache TinkerPop, Apache Hadoop, and Apache Groovy.
#### Alignment
HugeGraph implements the API of [Apache TinkerPop](https://tinkerpop.apache.org/), which defines the [Gremlin](https://tinkerpop.apache.org/gremlin.html). Gremlin is a powerful graph traversal language, and various complicated graph queries can be accomplished through Gremlin. The TinkerPop ecosystem based on Java is relatively mature in terms of graph databases. We use Java language, which is developed efficient and stable, to develop upper-level components like graph engine, graph computing, graph API, and graph tools; and we manage storage through JNI which is able to freely manage memory and execute efficiently.
### Known Risks
#### Project Name
We have checked and believe the name is [suitable](https://github.com/hugegraph/hugegraph/issues/1646) and the project has legal permission to continue using its current name. There are no other projects found using this name through Google Search.
#### Relationship with Titan/Janus Graph
In the early stage of the project, we referred to the storage structure of Titan/Janus Graph, some folks thought that HugeGraph was forked from Titan/Janus. In fact, HugeGraph is not based on these projects. HugeGraph is developed completely from scratch and in the process it addressed many new challenges. Certainly, the project was inspired by Titan/Janus and we are really grateful for these inspirations.
### Orphaned products
Due to a small and limited number of committers, the project has a relatively small risk of becoming an orphan project. However, the committers have been operating the HugeGraph Community for 3 years in the spirit of open-source, and continue to develop new contributors to participate.
#### Inexperience with Open-Source
HugeGraph has been open-sourced on GitHub for 3 years, during which committers submitted code and documents in full compliance with open-source specifications and requirements.
#### Length of Incubation
Expect to enter incubation in 4 months and graduate in about 2 years.
#### Homogenous Developers
The developers on the current list come from several different companies plus many independent volunteers, but the most of committers are from Baidu. The developers are geographically concentrated in China now. They are experienced with working in a distributed environment in other open-source projects, e.g. OpenStack.
#### Reliance on Salaried Developers
Most of the developers are paid by their employer to contribute to this project. Given some volunteer developers and the committers' sense of ownership for the code, the project could continue even if no salaried developers contributed to the project.
#### Relationships with Other Apache Products
HugeGraph follows the Apache TinkerPop specification, uses Apache Commons, Apache HttpClient, and Apache HttpCore to implement the basic functions. Users can choose Apache Cassandra or Apache HBase as one of the storage backends of HugeGraph.
#### An Excessive Fascination with the Apache Brand
Although we expect that the Apache brand may help attract more contributors, our interest in starting this project is based on the factors mentioned in the fundamentals section. We are interested in joining ASF to increase our connections in the open-source world. Based on extensive collaboration, it is possible to build a community of developers and committers that live longer than the founder.
### Documentation
HugeGraph documentation is provided on https://hugegraph.github.io/hugegraph-doc/ in Simplified Chinese, the complete English version of the documentation is being prepared.
### Initial Source
This project consists of 2 core sub-projects and 2 other sub-projects, all of which are hosted by [GitHub hugegraph organization](https://github.com/orgs/hugegraph/repositories) since 2018. The codes are already under Apache License Version 2.0. The git address of sub-project repositories are as follows:
1. The graph database repository `hugegraph`, core sub-project, including graph server, graph engine, and graph storage: https://github.com/hugegraph/hugegraph
2. The graph computing repository `hugegraph-computer`, core sub-project, including graph computing and graph algorithms: https://github.com/hugegraph/hugegraph-computer
3. The common functions repository `hugegraph-commons`: https://github.com/hugegraph/hugegraph-commons
4. The ecosystem repository `hugegraph-toolchain`, including `hugegraph-client`, `hugegraph-loader`, `hugegraph-tools`, `hugegraph-hubble`, `hugegraph-test`, `hugegraph-doc`: https://github.com/hugegraph/hugegraph-toolchain
### Source and Intellectual Property Submission Plan
The code is currently under Apache License Version 2.0, and it was verified there were no intellectual property or license issues when it was open-sourced by Baidu in 2018. Baidu will provide SGA and all committers will sign ICLA after HugeGraph is accepted into the Incubator.
#### External Dependencies
As all dependencies are managed by Apache Maven, none of the external libraries need to be packaged in a source distribution. All dependencies have Apache compatible licenses except for 4 dependencies: MySQL Connector (GPL), word (GPL), JBoss Logging 3 (LGPL), and jnr-posix (LGPL+GPL), we will remove these dependencies in the future.
HugeGraph has the following external [dependencies](https://github.com/hugegraph/hugegraph/issues/1632):
- Apache License
- HttpClient
- HttpCore
- Apache License 2.0
- Annotations for Metrics
- ansj_seg
- Apache Cassandra
- Apache Commons
- Apache Groovy
- Apache HttpClient
- Apache HttpCore
- Apache Ivy
- Apache Log4j
- Apache Thrift
- Apache TinkerPop
- Apache Yetus
- Bean Validation API
- Caffeine cache
- CLI
- Sofa
- ConcurrentLinkedHashMap
- Data Mapper for Jackson
- DataStax Java Driver for Apache Cassandra
- Disruptor Framework
- error-prone annotations
- exp4j
- fastutil
- Findbugs
- Google Android Annotations Library
- Gson
- Guava
- Hibernate Validator Engine
- HPPC Collections
- htrace-core4
- IKAnalyzer
- io.grpc
- J2ObjC Annotations
- Jackson
- Java Agent for Memory Measurements
- Java Concurrency Tools Core Library
- JavaPoet
- javatuples
- jcseg-core
- jffi
- JJWT
- jnr
- Joda
- jraft
- JSON.simple
- JVM Integration for Metrics
- Lucene
- LZ4 and xxHash
- Metrics
- mmseg4j-core
- Netty
- Ning-compress-LZF
- nlp-lang
- Objenesis
- OHC core
- OpenTracing
- perfmark
- picocli
- proto-google-common-protos
- sigar
- snappy-java
- stream-lib
- swagger
- Thrift Server implementation backed by LMAX Disruptor
- jieba for java
- Java Native Access
- HanLP
- SnakeYAML
- Apache License 2.0 + GPLv2 License
- RocksDB JNI
- BSD License
- ANTLR 3
- ASM
- Chinese to Pinyin
- Hamcrest
- JLine
- jcabi
- PostgreSQL JDBC Driver - JDBC 4.2
- Protocol Buffers
- StringTemplate
- CDDL + GPL License
- Grizzly
- Jersey
- CDDL + GPLv2 License
- glassfish
- Java Servlet API
- javax.ws.rs-api
- jersey-inject-hk2
- JSR 353 (JSON Processing) Default Provider
- Eclipse Distribution License
- Eclipse Collections
- JUnit
- ISC/BSD License
- jBCrypt
- LGPL License
- JBoss Logging 3
- LGPL + GPL License
- jnr-posix
- LGPL 2.1 + MPL 1.1 + Apache License 2.0
- Javassist
- MIT License
- Animal Sniffer Annotations
- Mockito
- SLF4J
- Jedis
- high-scale-lib
- jnr-x86asm
- GPL + MIT License
- Checker Qual
- GPL License
- MySQL Connector/J
- word
#### Cryptography
None
### Required Resources
#### Mailing lists
- hugegraph-dev: [dev@hugegraph.incubator.apache.org](mailto:dev@hugegraph.incubator.apache.org) for development and users discussions.
- hugegraph-private: [private@hugegraph.incubator.apache.org](mailto:private@hugegraph.incubator.apache.org) for PPMC discussions.
- hugegraph-commits: [commits@hugegraph.incubator.apache.org](mailto:commits@hugegraph.incubator.apache.org) for commits / [pull requests](https://github.com/hugegraph/hugegraph/pulls) and other notifications like code review comments.
#### Subversion Directory
None
#### Git Repositories
1. `hugegraph`: https://github.com/hugegraph/hugegraph.git
2. `hugegraph-computer`: https://github.com/hugegraph/hugegraph-computer.git
3. `hugegraph-commons`: https://github.com/hugegraph/hugegraph-commons.git
4. `hugegraph-toolchain`: https://github.com/hugegraph/hugegraph-toolchain.git
#### Issue Tracking
The community would like to continue using [GitHub Issues](https://github.com/hugegraph/hugegraph/issues) (but will move to github.com/apache/).
#### Other Resources
- The community has already chosen [GitHub actions](https://github.com/hugegraph/hugegraph/actions) as continuous integration tools.
- The community has already used [codecov](https://github.com/marketplace/codecov) to check code coverage.
- The community has already used [mvn repository](https://mvnrepository.com/search?q=hugegraph) as binary package release platform.
### Initial Committers
- Jermy Li (javaloveme at gmail dot com)
- Linary (liningrui at vip dot qq dot com)
- Zhoney (zhangyi89817 at 126 dot com)
- Imbajin (0x00 at imbajin.com)
- Vaughn (1318247699 at qq dot com)
- LiuNanke (liunanke at baidu dot com)
- Coderzc (zc1217zc at 126 dot com)
- ShouJing (1075185785 at qq dot com)
- Xiaobiao Li (13703287619 at 163 dot com)
- Haiping Huang (954872405 at qq dot com)
- Kidleaf Jiang (kidleaf at 163 dot com)
### Sponsors
#### Champion
- Willem Ning Jiang (ningjiang at apache dot org)
#### Nominated Mentors
- Trista Pan (panjuan at apache dot org)
- Lidong Dai (lidongdai at apache dot org)
- Xiangdong Huang (hxd at apache dot org)
- Yu Li (liyu at apache dot org)
#### Sponsoring Entity
We are expecting the Apache Incubator could sponsor this project.

View File

@ -1,35 +0,0 @@
name: "CLA Assistant"
on:
issue_comment:
types: [created]
pull_request_target:
types: [opened,closed,synchronize]
jobs:
CLAssistant:
runs-on: ubuntu-latest
steps:
- name: "CLA Assistant"
if: (github.event.comment.body == 'recheck' || github.event.comment.body == 'I have read the CLA Document and I hereby sign the CLA') || github.event_name == 'pull_request_target'
uses: cla-assistant/github-action@v2.1.3-beta
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
# the below token should have repo scope and must be manually added by you in the repository's secret
PERSONAL_ACCESS_TOKEN : ${{ secrets.PERSONAL_ACCESS_TOKEN }}
with:
path-to-signatures: '.github/cla-signatures/cla.json'
path-to-document: 'https://github.com/hugegraph/hugegraph-doc/blob/master/CLA.md' # e.g. a CLA or a DCO document
custom-allsigned-prcomment: '**Good**! All Contributors have signed the [CLA](https://github.com/hugegraph/hugegraph-doc/blob/master/CLA.md).'
# branch should not be protected
branch: 'cla-assist'
allowlist: bot*
lock-pullrequest-aftermerge: false
# the following are the optional inputs - If the optional inputs are not given, then default values will be taken
#remote-organization-name: enter the remote organization name where the signatures should be stored (Default is storing the signatures in the same repository)
#remote-repository-name: enter the remote repository name where the signatures should be stored (Default is storing the signatures in the same repository)
#create-file-commit-message: 'For example: Creating file for storing CLA Signatures'
#signed-commit-message: 'For example: $contributorName has signed the CLA in #$pullRequestNo'
#custom-notsigned-prcomment: 'pull request comment with Introductory message to ask new contributors to sign'
#custom-pr-sign-comment: 'The signature to be committed in order to sign the CLA'
#use-dco-flag: true - If you are using DCO instead of CLA

View File

@ -1,61 +0,0 @@
name: release package
on:
release:
types: [ published ]
jobs:
build:
runs-on: ubuntu-20.04
env:
TAG_NAME: ${{ github.ref_name }}
steps:
- name: Install JDK 8
uses: actions/setup-java@v2
with:
java-version: '8'
distribution: 'zulu'
- name: Cache Maven packages
uses: actions/cache@v3
with:
path: ~/.m2
key: ${{ runner.os }}-m2-${{ hashFiles('**/pom.xml') }}
restore-keys: ${{ runner.os }}-m2
- name: Checkout
uses: actions/checkout@v3
with:
fetch-depth: 2
- name: Package
run: |
mvn clean package -DskipTests -ntp
- name: Rename file
if: contains(env.TAG_NAME, "-")
run: mv "$(find hugegraph-*.tar.gz | head -1)" hugegraph-${TAG_NAME/#v/}.tar.gz
- name: Upload to GitHub
uses: xresloader/upload-to-github-release@master
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
with:
file: "hugegraph-*.tar.gz"
tag_name: ${{ github.ref_name }}
overwrite: true
verbose: true
draft: false
update_latest_release: true
- name: Release Maven package
uses: samuelmeuli/action-maven-publish@v1
with:
gpg_private_key: ${{ secrets.GPG_PRIVATE_KEY }}
gpg_passphrase: ${{ secrets.GPG_PASSPHRASE }}
nexus_username: ${{ secrets.NEXUS_USERNAME }}
nexus_password: ${{ secrets.NEXUS_PASSWORD }}
server_id: sonatype-nexus-staging
maven_profiles: "release"
maven_args: >
-Dmaven.test.skip=true

View File

@ -1,56 +0,0 @@
name: "3rd-party"
on:
push:
branches:
- /^release-.*$/
pull_request:
permissions:
contents: read
jobs:
dependency-check:
runs-on: ubuntu-latest
env:
USE_STAGE: 'true' # Whether to include the stage repository.
SCRIPT_DEPENDENCY: install-dist/scripts/dependency
steps:
- name: Checkout source
uses: actions/checkout@v4
- name: Set up JDK 11
uses: actions/setup-java@v3
with:
java-version: '11'
distribution: 'adopt'
- name: use staged maven repo settings
if: ${{ env.USE_STAGE == 'true' }}
run: |
cp $HOME/.m2/settings.xml /tmp/settings.xml
mv -vf .github/configs/settings.xml $HOME/.m2/settings.xml
- name: mvn install
run: |
mvn install -Dmaven.test.skip=true -ntp
- name: generate current dependencies
run: |
bash $SCRIPT_DEPENDENCY/regenerate_known_dependencies.sh current-dependencies.txt
- name: check third dependencies
run: |
bash $SCRIPT_DEPENDENCY/check_dependencies.sh
dependency-review:
runs-on: ubuntu-latest
steps:
- name: 'Checkout Repository'
uses: actions/checkout@v4
- name: 'Dependency Review'
uses: actions/dependency-review-action@v3
# Refer: https://github.com/actions/dependency-review-action
with:
# TODO: reset critical to low before releasing
fail-on-severity: critical
# Action will fail if dependencies don't match the list
#allow-licenses: Apache-2.0, MIT
#deny-licenses: GPL-3.0, AGPL-1.0, AGPL-3.0, LGPL-2.0, CC-BY-3.0

View File

@ -1,71 +0,0 @@
name: "CodeQL"
on:
push:
branches: [ master, release-* ]
pull_request:
# The branches below must be a subset of the branches above
# branches: [ master ] # enable in all PRs
schedule:
- cron: '33 0 * * 5'
jobs:
analyze:
env:
USE_STAGE: 'true' # Whether to include the stage repository.
name: Analyze
runs-on: ubuntu-latest
permissions:
actions: read
contents: read
security-events: write
strategy:
fail-fast: false
matrix:
language: [ 'java' ]
steps:
- name: Checkout repository
uses: actions/checkout@v4
- name: Setup Java JDK
uses: actions/setup-java@v3
with:
distribution: 'zulu'
java-version: '11'
- name: use staged maven repo settings
if: ${{ env.USE_STAGE == 'true' }}
run: |
cp $HOME/.m2/settings.xml /tmp/settings.xml
mv -vf .github/configs/settings.xml $HOME/.m2/settings.xml
# Initializes the CodeQL tools for scanning.
- name: Initialize CodeQL
uses: github/codeql-action/init@v2
with:
languages: ${{ matrix.language }}
# If you wish to specify custom queries, you can do so here or in a config file.
# By default, queries listed here will override any specified in a config file.
# Prefix the list here with "+" to use these queries and those in the config file.
# queries: ./path/to/local/query, your-org/your-repo/queries@main
# Autobuild attempts to build any compiled languages (C/C++, C#, or Java).
# If this step fails, then you should remove it and run the build manually (see below)
- name: Autobuild
uses: github/codeql-action/autobuild@v2
# Command-line programs to run using the OS shell.
# 📚 https://git.io/JvXDl
# ✏️ If the Autobuild fails above, remove it and uncomment the following three lines
# and modify them (or add more) to build your code if your project
# uses a compiled language
#- run: |
# make bootstrap
# make release
- name: Perform CodeQL Analysis
uses: github/codeql-action/analyze@v2

View File

@ -1,64 +0,0 @@
name: "HugeGraph-Commons CI"
on:
workflow_dispatch:
push:
branches:
- master
- /^release-.*$/
- /^test-.*$/
pull_request:
jobs:
build-commons:
runs-on: ubuntu-latest
env:
# TODO: reset use stage to false later
USE_STAGE: 'true' # Whether to include the stage repository.
strategy:
fail-fast: false
matrix:
JAVA_VERSION: ['11']
steps:
- name: Install JDK ${{ matrix.JAVA_VERSION }}
uses: actions/setup-java@v3
with:
java-version: ${{ matrix.JAVA_VERSION }}
distribution: 'zulu'
- name: Cache Maven packages
uses: actions/cache@v3
with:
path: ~/.m2
key: ${{ runner.os }}-m2-${{ hashFiles('**/pom.xml') }}
restore-keys: ${{ runner.os }}-m2
- name: Checkout
uses: actions/checkout@v3
with:
fetch-depth: 2
- name: Use staged maven repo settings
if: ${{ env.USE_STAGE == 'true' }}
run: |
cp $HOME/.m2/settings.xml /tmp/settings.xml
cp -vf .github/configs/settings.xml $HOME/.m2/settings.xml && cat $HOME/.m2/settings.xml
- name: Compile
run: |
mvn compile -Dmaven.javadoc.skip=true -ntp
- name: Run common test
run: |
mvn test -pl hugegraph-commons/hugegraph-common -Dtest=UnitTestSuite
- name: Run rpc test
run: |
mvn test -pl hugegraph-commons/hugegraph-rpc -Dtest=UnitTestSuite
- name: Upload coverage to Codecov
uses: codecov/codecov-action@v3.0.0
with:
file: target/jacoco.xml

View File

@ -1,31 +0,0 @@
name: "License Checker"
on:
push:
branches:
- master
- 'release-*'
pull_request:
jobs:
check-license:
runs-on: ubuntu-latest
env:
USE_STAGE: 'true' # Whether to include the stage repository.
steps:
- uses: actions/checkout@v4
- name: Check License Header
uses: apache/skywalking-eyes@main
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
with:
log: info
token: ${{ github.token }}
config: .licenserc.yaml
- name: License Check (RAT)
run: |
mvn apache-rat:check -ntp
find ./ -name rat.txt -print0 | xargs -0 -I file cat file > merged-rat.txt
grep "Binaries" merged-rat.txt -C 3 && cat merged-rat.txt

View File

@ -1,219 +0,0 @@
name: "HugeGraph-PD & Store & Hstore CI"
on:
push:
branches:
- master
- 'release-*'
- 'test-*'
pull_request:
# TODO: consider merge to one ci.yml file
jobs:
pd:
runs-on: ubuntu-latest
env:
# TODO: avoid duplicated env setup in pd & store
# TODO: reset use stage to false later
USE_STAGE: 'true' # Whether to include the stage repository.
# TODO: remove outdated env
TRAVIS_DIR: hugegraph-server/hugegraph-dist/src/assembly/travis
REPORT_DIR: target/site/jacoco
steps:
- name: Install JDK 11
uses: actions/setup-java@v3
with:
java-version: '11'
distribution: 'zulu'
- name: Cache Maven packages
uses: actions/cache@v3
with:
path: ~/.m2
key: ${{ runner.os }}-m2-${{ hashFiles('**/pom.xml') }}
restore-keys: ${{ runner.os }}-m2
- name: Checkout
uses: actions/checkout@v4
with:
fetch-depth: 5
- name: use staged maven repo settings
if: ${{ env.USE_STAGE == 'true' }}
run: |
cp $HOME/.m2/settings.xml /tmp/settings.xml
mv -vf .github/configs/settings.xml $HOME/.m2/settings.xml
- name: Run common test
run: |
mvn test -pl hugegraph-pd/hg-pd-test -am -P pd-common-test -DskipCommonsTests=true
- name: Run core test
run: |
mvn test -pl hugegraph-pd/hg-pd-test -am -P pd-core-test -DskipCommonsTests=true
# The above tests do not require starting a PD instance.
- name: Package
run: |
mvn clean package -U -Dmaven.javadoc.skip=true -Dmaven.test.skip=true -ntp
- name: Prepare env and service
run: |
$TRAVIS_DIR/start-pd.sh
- name: Run client test
run: |
mvn test -pl hugegraph-pd/hg-pd-test -am -P pd-client-test -DskipCommonsTests=true
- name: Run rest test
run: |
mvn test -pl hugegraph-pd/hg-pd-test -am -P pd-rest-test -DskipCommonsTests=true
- name: Upload coverage to Codecov
uses: codecov/codecov-action@v3.0.0
with:
file: ${{ env.REPORT_DIR }}/*.xml
store:
# TODO: avoid duplicated env setup
runs-on: ubuntu-latest
env:
USE_STAGE: 'true' # Whether to include the stage repository.
# TODO: remove outdated env
TRAVIS_DIR: hugegraph-server/hugegraph-dist/src/assembly/travis
REPORT_DIR: target/site/jacoco
steps:
- name: Install JDK 11
uses: actions/setup-java@v3
with:
java-version: '11'
distribution: 'zulu'
- name: Cache Maven packages
uses: actions/cache@v3
with:
path: ~/.m2
key: ${{ runner.os }}-m2-${{ hashFiles('**/pom.xml') }}
restore-keys: ${{ runner.os }}-m2
- name: Checkout
uses: actions/checkout@v4
with:
fetch-depth: 5
- name: use staged maven repo settings
if: ${{ env.USE_STAGE == 'true' }}
run: |
cp $HOME/.m2/settings.xml /tmp/settings.xml
mv -vf .github/configs/settings.xml $HOME/.m2/settings.xml
- name: Package
run: |
mvn clean package -U -Dmaven.javadoc.skip=true -Dmaven.test.skip=true -ntp
- name: Prepare env and service
run: |
$TRAVIS_DIR/start-pd.sh
$TRAVIS_DIR/start-store.sh
- name: Run common test
run: |
mvn test -pl hugegraph-store/hg-store-test -am -P store-common-test -DskipCommonsTests=true
- name: Run client test
run: |
mvn test -pl hugegraph-store/hg-store-test -am -P store-client-test -DskipCommonsTests=true
- name: Run core test
run: |
mvn test -pl hugegraph-store/hg-store-test -am -P store-core-test -DskipCommonsTests=true
- name: Run rocksdb test
run: |
mvn test -pl hugegraph-store/hg-store-test -am -P store-rocksdb-test -DskipCommonsTests=true
- name: Run server test
run: |
mvn test -pl hugegraph-store/hg-store-test -am -P store-server-test -DskipCommonsTests=true
- name: Run raft-core test
run: |
mvn test -pl hugegraph-store/hg-store-test -am -P store-raftcore-test -DskipCommonsTests=true
- name: Upload coverage to Codecov
uses: codecov/codecov-action@v3.0.0
with:
file: ${{ env.REPORT_DIR }}/*.xml
hstore:
# TODO: avoid duplicated env setup
runs-on: ubuntu-latest
env:
USE_STAGE: 'true' # Whether to include the stage repository.
TRAVIS_DIR: hugegraph-server/hugegraph-dist/src/assembly/travis
REPORT_DIR: target/site/jacoco
BACKEND: hstore
RELEASE_BRANCH: ${{ startsWith(github.ref_name, 'release-') || startsWith(github.ref_name, 'test-') || startsWith(github.base_ref, 'release-') }}
steps:
- name: Install JDK 11
uses: actions/setup-java@v3
with:
java-version: '11'
distribution: 'zulu'
- name: Cache Maven packages
uses: actions/cache@v3
with:
path: ~/.m2
key: ${{ runner.os }}-m2-${{ hashFiles('**/pom.xml') }}
restore-keys: ${{ runner.os }}-m2
- name: Checkout
uses: actions/checkout@v3
with:
fetch-depth: 2
- name: use staged maven repo settings
if: ${{ env.USE_STAGE == 'true' }}
run: |
cp $HOME/.m2/settings.xml /tmp/settings.xml
mv -vf .github/configs/settings.xml $HOME/.m2/settings.xml
- name: Package
run: |
mvn clean package -U -Dmaven.javadoc.skip=true -Dmaven.test.skip=true -ntp
- name: Prepare env and service
run: |
$TRAVIS_DIR/install-backend.sh $BACKEND
- name: Run unit test
run: |
$TRAVIS_DIR/run-unit-test.sh $BACKEND
- name: Run core test
run: |
$TRAVIS_DIR/run-core-test.sh $BACKEND
- name: Run api test
run: |
$TRAVIS_DIR/run-api-test.sh $BACKEND $REPORT_DIR
- name: Run raft test
if: ${{ env.BACKEND == 'rocksdb' }}
run: |
$TRAVIS_DIR/run-api-test-for-raft.sh $BACKEND $REPORT_DIR
- name: Run TinkerPop test
if: ${{ env.RELEASE_BRANCH == 'true' }}
run: |
$TRAVIS_DIR/run-tinkerpop-test.sh $BACKEND tinkerpop
- name: Upload coverage to Codecov
uses: codecov/codecov-action@v3.0.0
with:
file: ${{ env.REPORT_DIR }}/*.xml

View File

@ -1,101 +0,0 @@
name: "HugeGraph-Server CI"
on:
push:
branches:
- master
- 'release-*'
- 'test-*'
pull_request:
jobs:
build-server:
# TODO: we need test & replace it to ubuntu-24.04 or ubuntu-latest
runs-on: ubuntu-20.04
env:
# TODO: reset use stage to false later
USE_STAGE: 'true' # Whether to include the stage repository.
TRAVIS_DIR: hugegraph-server/hugegraph-dist/src/assembly/travis
REPORT_DIR: target/site/jacoco
BACKEND: ${{ matrix.BACKEND }}
TRIGGER_BRANCH_NAME: ${{ github.ref_name }}
HEAD_BRANCH_NAME: ${{ github.head_ref }}
BASE_BRANCH_NAME: ${{ github.base_ref }}
TARGET_BRANCH_NAME: ${{ github.base_ref != '' && github.base_ref || github.ref_name }}
RELEASE_BRANCH: ${{ startsWith(github.ref_name, 'release-') || startsWith(github.ref_name, 'test-') }}
RAFT_MODE: ${{ startsWith(github.head_ref, 'test') || startsWith(github.head_ref, 'raft') }}
strategy:
fail-fast: false
matrix:
BACKEND: [ memory, rocksdb, hbase, cassandra, mysql, postgresql, scylladb ]
JAVA_VERSION: [ '11' ]
steps:
- name: Checkout
uses: actions/checkout@v4
with:
fetch-depth: 5
# TODO: Remove this step after install-backend.sh updated
- name: Install Java8 for backend
uses: actions/setup-java@v3
with:
java-version: '8'
distribution: 'zulu'
- name: Prepare backend environment
run: |
$TRAVIS_DIR/install-backend.sh $BACKEND && jps -l
- name: Install Java ${{ matrix.JAVA_VERSION }}
uses: actions/setup-java@v3
with:
java-version: ${{ matrix.JAVA_VERSION }}
distribution: 'zulu'
- name: Cache Maven packages
uses: actions/cache@v3
with:
path: ~/.m2
key: ${{ runner.os }}-m2-${{ hashFiles('**/pom.xml') }}
restore-keys: ${{ runner.os }}-m2
- name: Use staged maven repo settings
if: ${{ env.USE_STAGE == 'true' }}
run: |
cp $HOME/.m2/settings.xml /tmp/settings.xml
cp -vf .github/configs/settings.xml $HOME/.m2/settings.xml && cat $HOME/.m2/settings.xml
- name: Compile
run: |
mvn clean compile -U -Dmaven.javadoc.skip=true -ntp
- name: Run unit test
run: |
$TRAVIS_DIR/run-unit-test.sh $BACKEND
- name: Run core test
run: |
$TRAVIS_DIR/run-core-test.sh $BACKEND
- name: Run api test
run: |
$TRAVIS_DIR/run-api-test.sh $BACKEND $REPORT_DIR
# TODO: disable raft test in normal PR due to the always timeout problem
- name: Run raft test
if: ${{ env.RAFT_MODE == 'true' && env.BACKEND == 'rocksdb' }}
run: |
$TRAVIS_DIR/run-api-test-for-raft.sh $BACKEND $REPORT_DIR
- name: Run TinkerPop test
if: ${{ env.RELEASE_BRANCH == 'true' }}
run: |
$TRAVIS_DIR/run-tinkerpop-test.sh $BACKEND tinkerpop
- name: Upload coverage to Codecov
uses: codecov/codecov-action@v3
with:
token: ${{ secrets.CODECOV_TOKEN }}
file: ${{ env.REPORT_DIR }}/*.xml

View File

@ -1,38 +0,0 @@
name: "Mark stale issues and pull requests"
on:
schedule:
- cron: "0 21 * * *"
jobs:
stale:
runs-on: ubuntu-latest
permissions:
issues: write
pull-requests: write
steps:
- uses: actions/stale@v3
with:
repo-token: ${{ secrets.GITHUB_TOKEN }}
stale-issue-message: 'Due to the lack of activity, the current issue is marked as stale and will be closed after 20 days, any update will remove the stale label'
stale-pr-message: 'Due to the lack of activity, the current pr is marked as stale and will be closed after 180 days, any update will remove the stale label'
stale-issue-label: 'inactive'
stale-pr-label: 'inactive'
exempt-issue-labels: 'feature,bug,enhancement,improvement,todo,guide,doc,help wanted,security'
exempt-pr-labels: 'feature,bug,enhancement,improvement,todo,guide,doc,help wanted,security'
exempt-all-milestones: true
days-before-issue-stale: 15
days-before-issue-close: 20
days-before-pr-stale: 30
days-before-pr-close: 180
operations-per-run: 10
start-date: '2016-10-01T00:00:00Z'
exempt-all-assignees: true
remove-stale-when-updated: true
exempt-all-pr-milestones: true
delete-branch: false
enable-statistics: true

89
.gitignore vendored
View File

@ -1,51 +1,6 @@
target/
**.db
logs/
ui
node_modules
upload-files/
demo*
gen-java
*.class
### STS ###
.apt_generated
.classpath
.factorypath
.project
.settings
.springBeans
.sts4-cache
.svn
### IntelliJ IDEA ###
.idea/*
!.idea/vcs.xml
!.idea/icon.png
*.iws
*.iml
*.ipr
### NetBeans ###
/nbproject/private/
/nbbuild/
/nbdist/
/.nb-gradle/
dist/
build/
### VS Code ###
.vscode/
# misc
.DS_Store
*/.DS_Store
**/*.DS_Store
.env.local
.env.development.local
.env.test.local
.env.production.local
*.iml
*.iws
*.orig
*.rej
**/.keep
@ -55,35 +10,11 @@ build/
*.swp
*.log
*.pyc
# maven ignore
apache-hugegraph-*/
output/
*.war
*.zip
*.tar
*.tar.gz*
tree.txt
*.versionsBackup
.flattened-pom.xml
# eclipse ignore
.settings/
# temp ignore
*.cache
*.diff
*.patch
*.tmp
# system ignore
Thumbs.db
hs_err_pid*
# mobile Tools for Java (J2ME)
.mtj.tmp/
# blueJ files
*.ctxt
# docker volumes ignore
hugegraph-server/hugegraph-dist/docker/data/
.idea
.svn
.classpath
.project
.settings
target
gen-java
build

Binary file not shown.

Before

Width:  |  Height:  |  Size: 8.3 KiB

View File

@ -1,37 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<!--
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.
-->
<project version="4">
<component name="IssueNavigationConfiguration">
<option name="links">
<list>
<IssueNavigationLink>
<option name="issueRegexp" value="#(\d+)" />
<!--
GitHub share the sequence number of issues and pull requests, and it will redirect to
the right place when the the sequence number not match kind.
-->
<option name="linkRegexp" value="https://github.com/apache/hugegraph/pull/$1" />
</IssueNavigationLink>
</list>
</option>
</component>
<component name="VcsDirectoryMappings">
<mapping directory="$PROJECT_DIR$" vcs="Git" />
</component>
</project>

View File

@ -1,107 +0,0 @@
#
# 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.
#
header: # `header` section is configurations for source codes license header.
license:
spdx-id: Apache-2.0 # the spdx id of the license, it's convenient when your license is standard SPDX license.
copyright-owner: Apache Software Foundation # the copyright owner to replace the [owner] in the `spdx-id` template.
content: | # `license` will be used as the content when `fix` command needs to insert a license header.
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.
# `pattern` is optional regexp if all the file headers are the same as `license` or the license of `spdx-id` and `copyright-owner`.
pattern: |
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.
paths: # `paths` are the path list that will be checked (and fixed) by license-eye, default is ['**'].
- '**'
paths-ignore: # `paths-ignore` are the path list that will be ignored by license-eye.
- '.gitignore'
- '.gitattributes'
- 'LICENSE'
- 'NOTICE'
- 'DISCLAIMER'
- '**/*.versionsBackup'
- '**/*.versionsBackup'
- '**/*.proto'
- '**/*.log'
- '**/*.txt'
- '**/*.json'
- '**/*.conf'
- '**/*.map'
- '**/*.properties'
- '**/RaftRequests.java'
- 'dist/**/*'
- 'hugegraph-server/hugegraph-dist'
- '**/assembly/static/bin/hugegraph.service'
- 'scripts/dev/reviewers'
- 'scripts/dev/reviewers'
- '**/*.md'
- '**/dependency-reduced-pom.xml'
- '**/logs/*.log'
- '**/META-INF/**/*'
- '**/target/*'
- 'style/*'
- 'ChangeLog'
- 'CONFIG.ini'
- 'GROUPS'
- 'OWNERS'
- '.github/**/*'
- '**/*.iml'
- '**/*.iws'
- '**/*.ipr'
- '**/META-INF/MANIFEST.MF'
- '.repository/**'
- '**/.flattened-pom.xml'
- 'hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/backend/id/SnowflakeIdGenerator.java'
- 'hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/traversal/optimize/HugeScriptTraversal.java'
- 'hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/type/Nameable.java'
- 'hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/type/define/Cardinality.java'
- 'hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/util/StringEncoding.java'
- 'hugegraph-server/hugegraph-test/src/main/java/org/apache/hugegraph/tinkerpop/ProcessBasicSuite.java'
- 'hugegraph-server/hugegraph-test/src/main/java/org/apache/hugegraph/tinkerpop/StructureBasicSuite.java'
- 'hugegraph-server/hugegraph-api/src/main/java/org/apache/hugegraph/opencypher/CypherOpProcessor.java'
- 'hugegraph-server/hugegraph-api/src/main/java/org/apache/hugegraph/opencypher/CypherPlugin.java'
comment: on-failure # on what condition license-eye will comment on the pull request, `on-failure`, `always`, `never`.
# license-location-threshold specifies the index threshold where the license header can be located,
# after all, a "header" cannot be TOO far from the file start.
license-location-threshold: 80

22
.maven.xml Normal file
View File

@ -0,0 +1,22 @@
<settings>
<servers>
<server>
<id>ossrh</id>
<username>${env.MAVEN_REPO_USERNAME}</username>
<password>${env.MAVEN_REPO_PASSWORD}</password>
</server>
</servers>
<profiles>
<profile>
<id>release</id>
<activation>
<activeByDefault>true</activeByDefault>
</activation>
<properties>
<gpg.executable>gpg</gpg.executable>
<gpg.keyname>${env.GPG_KEY_ID}</gpg.keyname>
<gpg.passphrase>${env.GPG_PASSPHRASE}</gpg.passphrase>
</properties>
</profile>
</profiles>
</settings>

BIN
.private-key.gpg.gpg Normal file

Binary file not shown.

View File

@ -1,122 +1,62 @@
language: java
jdk:
- openjdk8
dist: xenial
- oraclejdk8
sudo: required
cache:
directories:
- $HOME/.m2
- $HOME/downloads
services:
- cassandra
- mysql
branches:
only:
- master
- /^release-.*$/
- /^test-.*$/
- /^v[0-9]\..*$/
addons:
apt:
sources:
- mysql-5.7-trusty
packages:
- mysql-server
- mysql-client
install: mvn compile -Dmaven.javadoc.skip=true | grep -v "Downloading\|Downloaded"
install: mvn compile
before_script:
- $TRAVIS_DIR/install-backend.sh
script: mvn test -Pcore-test,$BACKEND
script:
- mvn test -P core-test,$BACKEND
- $TRAVIS_DIR/run-api-test.sh
- $TRAVIS_DIR/run-unit-test.sh
before_deploy:
- |
if [ "$DEPLOYED" == "false" ]; then
DEPLOYED=true
mvn cobertura:cobertura > /dev/null && bash <(curl -s https://codecov.io/bash)
mvn clean package -DskipTests
else
echo "Skipping before_deploy since it has been executed once."
fi
after_success:
- bash <(curl -s https://codecov.io/bash)
jobs:
include:
- stage: tinkerpop-test
if: branch =~ env(RELEASE_BRANCH)
env: BACKEND=memory SUITE=tinkerpop
script: $TRAVIS_DIR/run-tinkerpop-test.sh
- stage: tinkerpop-test
if: branch =~ env(RELEASE_BRANCH)
env: BACKEND=cassandra SUITE=tinkerpop
script: $TRAVIS_DIR/run-tinkerpop-test.sh
- stage: tinkerpop-test
if: branch =~ env(RELEASE_BRANCH)
env: BACKEND=scylladb SUITE=tinkerpop
script: $TRAVIS_DIR/run-tinkerpop-test.sh
- stage: tinkerpop-test
if: branch =~ env(RELEASE_BRANCH)
env: BACKEND=mysql SUITE=tinkerpop
script: $TRAVIS_DIR/run-tinkerpop-test.sh
- stage: tinkerpop-test
if: branch =~ env(RELEASE_BRANCH)
env: BACKEND=hbase SUITE=structure
script: $TRAVIS_DIR/run-tinkerpop-test.sh
- stage: tinkerpop-test
if: branch =~ env(RELEASE_BRANCH)
env: BACKEND=hbase SUITE=process
script: $TRAVIS_DIR/run-tinkerpop-test.sh
- stage: tinkerpop-test
if: branch =~ env(RELEASE_BRANCH)
env: BACKEND=rocksdb SUITE=tinkerpop
script: $TRAVIS_DIR/run-tinkerpop-test.sh
- stage: tinkerpop-test
if: branch =~ env(RELEASE_BRANCH)
env: BACKEND=postgresql SUITE=tinkerpop
script: $TRAVIS_DIR/run-tinkerpop-test.sh
- stage: deploy
if: tag =~ env(RELEASE_TAG)
script: skip
before_deploy:
- |
if [ $DEPLOYED = 0 ]; then
DEPLOYED=1
mvn clean package -DskipTests
else
echo "Skipping before_deploy since it has been executed once."
fi
deploy:
- provider: releases
skip_cleanup: true
file_glob: true
file: "$TRAVIS_BUILD_DIR/hugegraph-*.tar.gz"
api_key:
secure: nSGEnk5tJsTHMGABO8OJMTk47L3QA2O4xHXLKGIuTK5kLGJkrl0Bs27IveggLxf1E7DSrhcfNW44yIjn5lWA/5QX3DweWH4FGDAgWYFyj7QsBZl7WT2NReMW7BLzpvsIjyEKDw5pLbYBOpOrHflmyQB4w0oXTZVl6awll7JicuL1air7lpqJ4Ju4ukj1mo6rcX3MHRkzgMuS5eemArm8T15y9IlDqK3gmjVUOVo7LoYDFaq3eMzQ7ufrOFiiVIV2LUxn2t2/YRcKU05zal4IKifMKbXISX5u7ZwYe8T14ZQ7eMTOzmFY21gv3HEg+KXWh4gq8HvG4FKbzrl+KYSacJ1xINJQaQGIOD7Pz7vzQdj9wpM/WLqmYF5SE5ZYzXV3ejrtYlEUpJQSnpyiHlfyRuDRzYq/dB2V1ua6t9xkbjL/a2uqHa9WjbOi1jqw2E2XSnx794pzCvKYn1RLOiqpzVlEnb3cPb5M7vl9wsGf5MFLS8zLmMa5DyJn+e45W6GpW1zT4uLl2yR3Ja9ROlVapAb4aMyhKnWQZtUMDVhD6Xjj/CAumeOQLe31NM3i8NK2L0iEYSFWUigLEcCapXo3aOVlzckdJ6p7k94dFd5wcg/EY2aFMhyjYUKUFP1V535uB4ZKvf/dotMKY29nsYyceYgOJ/VNZt2BPZ8oCdc8+ys=
on:
tags: true
- provider: script
skip_cleanup: true
script:
echo $GPG_KEY_ENC_PASSW | gpg -d --passphrase-fd 0 $TRAVIS_DIR/private-key.gpg.gpg | gpg --import &&
mvn deploy --settings $TRAVIS_DIR/maven.xml -DskipTests=true -B -U -P release
on:
tags: true
deploy:
- provider: script
skip_cleanup: true
script:
echo $GPG_KEY_ENC_PASSW | gpg -d --passphrase-fd 0 .private-key.gpg.gpg | gpg --import &&
mvn deploy --settings .maven.xml -DskipTests=true -B -U -Prelease
on:
tags: true
- provider: releases
skip_cleanup: true
file_glob: true
file: "$TRAVIS_BUILD_DIR/hugegraph-*.tar.gz"
api_key:
secure: nSGEnk5tJsTHMGABO8OJMTk47L3QA2O4xHXLKGIuTK5kLGJkrl0Bs27IveggLxf1E7DSrhcfNW44yIjn5lWA/5QX3DweWH4FGDAgWYFyj7QsBZl7WT2NReMW7BLzpvsIjyEKDw5pLbYBOpOrHflmyQB4w0oXTZVl6awll7JicuL1air7lpqJ4Ju4ukj1mo6rcX3MHRkzgMuS5eemArm8T15y9IlDqK3gmjVUOVo7LoYDFaq3eMzQ7ufrOFiiVIV2LUxn2t2/YRcKU05zal4IKifMKbXISX5u7ZwYe8T14ZQ7eMTOzmFY21gv3HEg+KXWh4gq8HvG4FKbzrl+KYSacJ1xINJQaQGIOD7Pz7vzQdj9wpM/WLqmYF5SE5ZYzXV3ejrtYlEUpJQSnpyiHlfyRuDRzYq/dB2V1ua6t9xkbjL/a2uqHa9WjbOi1jqw2E2XSnx794pzCvKYn1RLOiqpzVlEnb3cPb5M7vl9wsGf5MFLS8zLmMa5DyJn+e45W6GpW1zT4uLl2yR3Ja9ROlVapAb4aMyhKnWQZtUMDVhD6Xjj/CAumeOQLe31NM3i8NK2L0iEYSFWUigLEcCapXo3aOVlzckdJ6p7k94dFd5wcg/EY2aFMhyjYUKUFP1V535uB4ZKvf/dotMKY29nsYyceYgOJ/VNZt2BPZ8oCdc8+ys=
on:
tags: true
env:
matrix:
- BACKEND=memory
- BACKEND=cassandra
- BACKEND=scylladb
- BACKEND=mysql
- BACKEND=hbase
- BACKEND=rocksdb
- BACKEND=postgresql
- BACKEND=mysql
global:
- RELEASE_BRANCH=^release-.*$
- RELEASE_TAG=^v[0-9]\..*$
- TRAVIS_DIR=hugegraph-server/hugegraph-dist/src/assembly/travis
- DEPLOYED=0
- DEPLOYED=false
- secure: dYmFTVeEtRzLNaHp9ToTV/+CkTD0/rEj+K7dRN8wsv/yg4pbqwnyWbSXcqMlj6iNFzAz3nPbmFLCvAWON9/SMN9iJIT6x/xfcf+LqCT8QWczo2nc9xeX144ij2VHX1Drvtk5fRTMaTXRfWEQIrjqx2yrJTIdrXWzWSaZLFv1CRCUizEiGGCePnzUWxx9dBypNyC6IaH6lIv8uN5E6+10SYhb7UJGjWUMDg1bCeW9X7X2wg4QpsGDzlGFXT2EBPU/dAb5attTAtW8dKxrCZqZJTPWe0BarXDBR4PO15BC+a0V1g8LwexedtDjJeFRcGPaJ5NN4d3jDSusCzt5Jf4U0Wa1gDRMVTU3jT+KYkm5eoV4wOZMySobjh6VpQH/LyL0QTDy5apRPAxw+wO+tc91P+nkJmnlr3pN8abtMZ6NciZizUBYQRgR/m2Ir0stvtbZxBQOATuPtBgNDKiDgVdSYcRJzSqYEMFOn35AvsDZ9aUsyC8k29PCUZ0gQO2Is6cV1ClFBnM52hfU9XX0gu+NviSnYNGvcokod8z9VjGtnM7V3LYjqXSFqO9kkMbOmkME1tD2Bh/klw2/OM+2tBBZiAgxB89st5jSUHI4a2hpUyaQBezJUcU9t2vVT/zAVEIqzw2PDxkMU7t0n6L1x+qUIUTG/WynfIni5msxuR7HoiU=
- secure: XbX6AX5zDPc2PcWYAMW+6fazqRRUqpgQkt4eXUugLuVIYZBmJ0WqncEhJ4+mdwOGPIhnP2HsOaSeK2eE/O+iLY2XpBFbugoBgm9VaZlCC4CY1gRNHaanYg64Lrm3NPY3n08IHRMazHqMpJwUqNO+OG/6QwkepULQLj5Rluf716AoXHa7IEJhAIrwr+OXQvdEaJdUXlS1lRycXVeYtOewl7qYxCO4dD4RMhPlNykh9KEK7fd5wnPkiUsp1SwF4g5XsaLvGXmT/qQ1nj8oa9Caej/iaj6HMKG3BO057mq4KK5JDxTPWhBueNpEkUwldAnrMhYWLRnNf4IyjUsaB/Pmi6HspzcaiORPLYwPmdvLGGSnYwbtO+fAHebgpgOnj/vGmRmY4YtIkYdFtbPBI0HpbGB77tqNRFCe/5deLrjx0hXJBfoKTy7d42SI1eBhNR0svZYUHkSfuXwly6hMTlH1DN/bumMFxfXDkY9PFHlzV1Mn3vb9BxKTaP88hJsWk7JqgniqUF7EWAc0EhHMbJct2gC0pDc95z4Yy9391n7/XWJErhIdYon1Ukds5+a43xFXoy76gR4LuMDpzzCnutMjhC2yDuGaZx/DfkPBb5JFU7SHtTKj05zb73Moogi7qqbH8jwcwoSfogAKyrIAWTcAgvJ2LVnRzwdsiLTc6MEagiM=
- secure: GKdjRHR35FBPY6oGBfjVdGxnVeoMmZHgNCnsyGNvRVJiQLhXBjUQ9bYjxPRX3JkmztdofNVd3gV8xqIOfLD6XA/0qHVvZ5GlWK4O77eGDur5InobzMlRDIUvJkpqM2SdSU8vKoAUBWgKnfzvlbA14kiwCID72zDVa/E8G0gBl0GZ2zWXIWRg0zC3ZyaJwTZC8WLqn0Kl7UxMy6i/xmK1F+apLooFIBEXYZuoH3pY83L4BvPozmJzT66HonrfcnaifaVHShBntPhQ6Sjlq5suMhtQENcPqWxaORL69s6Y/uF+RAdmnRHPZnXFhjRvq3rQAdMKM/DBOcaYlu1aIxCJJmWLm+b+75EQgdtwYGtwDpunzKXzH7ewB6rTYAghJNjGxt/KfROniooAs8mO3DqhygV5/BInJk0aKab5GlHCAioesV7TKSObhSDlKU8CSBRr/j8T7anL+lkXVZ89fkGg+EBSoXkVCNwQjank1NrHWCJQpNVndHzWIoGk0gcjTf01+iMDGIJDQZhcEuLu8wZbvDjLo/qEah247G0JabDMNBdyMZpg96bWDgArMkWa2FnWX25A7Cfgm1JymXdOZCIJrHbYWWAyoaXNrjZezQ8NPnE5uOWJIKfBnjnyPtKPoWjLuqpXmqcggbl8iRiy1EdWs/N39Q7qcFtJ5lTN9q1kDeI=

1
BCLOUD Normal file
View File

@ -0,0 +1 @@
BUILD_SUBMITTER -x -e CENTOS6U3 -m baidu/xbu-data/hugegraph -c "export MAVEN_HOME=/home/scmtools/buildkit/maven/apache-maven-3.3.9/ && export JAVA_HOME=/home/scmtools/buildkit/java/jdk1.8.0_25/ && export PATH=$JAVA_HOME/bin:$MAVEN_HOME/bin:$PATH && cd baidu/xbu-data/hugegraph && sh build.sh && mkdir output && cp BCLOUD ./output/" -u ./

View File

@ -1,35 +1,28 @@
Building HugeGraph
Building hugegraph
--------------
Required:
* Java 11
* Maven 3.5+
To build without executing tests: `mvn clean package -Dmaven.test.skip=true`
## Building in IDEA
* Java 8 (0.9 and later)
* Maven
To build without executing tests:
1. Click on "File" -> "Open", choose your project location.
2. Open maven view by click "View" -> "Tool Windows" -> "Maven Projects".
3. Choose root module "hugegraph: Distributed Graph Database", unfold the menu of "Lifecycle".
4. Click the "Toggle 'Skip Tests' Mode" button which is located on the top navibar of "Maven Projects" window to skip tests.
5. Double click "package" or "install" to build a project.
```
mvn clean
mvn package -DskipTests
```
Could also refer [Dev-In-IDEA](https://hugegraph.apache.org/docs/contribution-guidelines/hugegraph-server-idea-setup/) for more details.
## Building on Eclipse IDE
Note that this has only been tested on Eclipse Neon.2 Release (4.6.2) with m2e (1.7.0.20160603-1933) and m2e-wtp (1.3.1.20160831-1005) plugin.
## Building in Eclipse
> Note: this has only been tested on Eclipse Neon.2 Release (4.6.2) with m2e (1.7.0.20160603-1933) and m2e-wtp (1.3.1.20160831-1005) plugin.
To build without executing tests:
1. Right-click on your project -> "Run As..." -> "Run Configurations..."
2. On "Goals", populate with `install`
3. Select the options `Update Snapshots` and `Skip Tests`
4. Before clicking "Run", make sure that Eclipse knows where `JAVA_HOME` is. In the same window, go to "Environment" tab and click "New".
4. Before clicking "Run", make sure that Eclipse knows where `JAVA_HOME` is. On same window, go to "Environment" tab and click "New".
5. Under "Name:", add `JAVA_HOME`
6. Under "Value:", add the path where `java` is located
7. Click "OK"
@ -39,3 +32,14 @@ To find the Java binary in your environment, run the appropriate command for you
* Linux/macOS: `which java`
* Windows: `for %i in (java.exe) do @echo. %~$PATH:i`
## Building on IDEA
To build without executing tests:
1. Click on "File" -> "Open", choose your project location.
2. Open maven view by click "View" -> "Tool Windows" -> "Maven Porjects".
3. Choose root module "hugegraph: Distributed Graph Database", unfold the
menu of "Lifecycle".
4. Click the "Toggle 'Skip Tests' Mode" button which is located on the top
navibar of "Maven Projects" window to skip tests.
5. Double click "package" or "install" to build project.

View File

@ -1,180 +0,0 @@
# How to Contribute to HugeGraph
> Refer [website-doc](https://hugegraph.apache.org/docs/contribution-guidelines/) for the latest information.
Thanks for taking the time to contribute!
As an open source project, HugeGraph is looking forward to being contributed from everyone, and we are also grateful to all the contributors.
The following is a contribution guide for HugeGraph:
<img width="884" alt="image" src="https://user-images.githubusercontent.com/9625821/159643158-8bf72c0a-93c3-4a58-8912-7b2ab20ced1d.png">
## 1. Preparation
**Recommended**: You can use [GitHub desktop](https://desktop.github.com/) to greatly simplify the PR process.
We can contribute by reporting issues, submitting code patches or any other feedback.
Before submitting the code, we need to do some preparation:
1. Sign up or login to GitHub: [https://github.com](https://github.com)
2. Fork HugeGraph repo from GitHub: [https://github.com/apache/incubator-hugegraph/fork](https://github.com/apache/incubator-hugegraph/fork)
3. Clone code from fork repo to local: [https://github.com/${GITHUB_USER_NAME}/incubator-hugegraph](https://github.com/${GITHUB_USER_NAME}/incubator-hugegraph)
```shell
# clone code from remote to local repo
git clone https://github.com/${GITHUB_USER_NAME}/incubator-hugegraph.git hugegraph
```
4. Configure local HugeGraph repo
```shell
cd hugegraph
# add upstream to synchronize the latest code
git remote add hugegraph https://github.com/apache/incubator-hugegraph
# set name and email to push code to github
git config user.name "{full-name}" # like "Jermy Li"
git config user.email "{email-address-of-github}" # like "jermy@apache.org"
```
## 2. Create an Issue on GitHub
If you encounter bugs or have any questions, please go to [GitHub Issues](https://github.com/apache/incubator-hugegraph/issues) to report them and feel free to [create an issue](https://github.com/apache/incubator-hugegraph/issues/new).
## 3. Make changes of code locally
#### 3.1 Create a new branch
Please don't use master branch for development. Instead, we should create a new branch:
```shell
# checkout master branch
git checkout master
# pull the latest code from official hugegraph
git pull hugegraph
# create new branch: bugfix-branch
git checkout -b bugfix-branch
```
#### 3.2 Change the code
Assume that we need to modify some files like "HugeGraph.java" and "HugeFactory.java":
```shell
# modify code to fix a bug
vim hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/HugeGraph.java
vim hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/HugeFactory.java
# run test locally (optional)
mvn test -Pcore-test,memory
```
Note: To be consistent with the code style easily, if you use [IDEA](https://www.jetbrains.com/idea/) as your IDE, you can directly [import](https://www.jetbrains.com/help/idea/configuring-code-style.html) our code style [configuration file](./hugegraph-style.xml).
##### 3.2.1 Check licenses
If we want to add new third-party dependencies to the `HugeGraph` project, we need to do the following things:
1. Find the third-party dependent repository, put the dependent `license` file into [./hugegraph-dist/release-docs/licenses/](https://github.com/apache/incubator-hugegraph/tree/master/hugegraph-dist/release-docs/licenses) path.
2. Declare the dependency in [./hugegraph-server/hugegraph-dist/release-docs/LICENSE](https://github.com/apache/incubator-hugegraph/blob/master/hugegraph-server/hugegraph-dist/release-docs/LICENSE) `LICENSE` information.
3. Find the NOTICE file in the repository and append it to [./hugegraph-server/hugegraph-dist/release-docs/NOTICE](https://github.com/apache/incubator-hugegraph/blob/master/hugegraph-server/hugegraph-dist/release-docs/NOTICE) file (skip this step if there is no NOTICE file).
4. Execute locally [./hugegraph-server/hugegraph-dist/scripts/dependency/regenerate_known_dependencies.sh](https://github.com/apache/incubator-hugegraph/blob/master/hugegraph-server/hugegraph-dist/scripts/dependency/regenerate_known_dependencies.sh) to update the dependency list [known-dependencies.txt](https://github.com/apache/incubator-hugegraph/blob/master/hugegraph-server/hugegraph-dist/scripts/dependency/known-dependencies.txt) (or manually update).
**Example**: A new third-party dependency is introduced into the project -> `ant-1.9.1.jar`
- The project source code is located at: https://github.com/apache/ant/tree/rel/1.9.1
- LICENSE file: https://github.com/apache/ant/blob/rel/1.9.1/LICENSE
- NOTICE file: https://github.com/apache/ant/blob/rel/1.9.1/NOTICE
The license information of `ant-1.9.1.jar` needs to be specified in the LICENSE file, and the notice information needs to be specified in the NOTICE file. The detailed LICENSE file corresponding to ant-1.9.1.jar needs to be copied to our licenses/ directory. Finally, update the known-dependencies.txt file.
#### 3.3 Commit changes to git repo
After the code has been completed, we submit them to the local git repo:
```shell
# add files to local git index
git add hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/HugeGraph.java
git add hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/HugeFactory.java
# commit to local git repo
git commit
```
Please edit the commit message after running `git commit`, we can explain what and how to fix a bug or implement a feature, the following is an example:
```sh
Fix bug: run deploy multiple times
fix #ISSUE_ID
```
> Please remember to fill in the issue id, which GitHub generated after issue creation.
#### 3.4 Push commit to GitHub fork repo
Push the local commit to GitHub fork repo:
```shell
# push the local commit to fork repo
git push origin bugfix-branch:bugfix-branch
```
Note that since GitHub requires submitting code through `username + token` (instead of using `username + password` directly), you need to create a GitHub token from https://github.com/settings/tokens:
<img width="1280" alt="image" src="https://user-images.githubusercontent.com/9625821/163524204-7fe0e6bf-9c8b-4b1a-ac65-6a0ac423eb16.png">
## 4. Create a Pull Request
Go to the web page of GitHub fork repo, there would be a chance to create a Pull Request after pushing to a new branch, click the button "Compare & pull request" to do it. Then edit the description for proposed changes, which can just be copied from the commit message.
Note: please make sure the email address you used to submit the code is bound to the GitHub account. For how to bind the email address, please refer to https://github.com/settings/emails:
<img width="1280" alt="image" src="https://user-images.githubusercontent.com/9625821/163522445-2a50a72a-dea2-434f-9868-3a0d40d0d037.png">
## 5. Code review
Maintainers will start the code review after all the **automatic** checks are passed:
- Check: Contributor License Agreement is signed
- Check: Travis CI builds are passed (automatically Test and Deploy)
The commit will be accepted and merged if there is no problem after review.
Please click on "Details" to find the problem if any check does not pass.
If there are checks not passed or changes requested, then continue to modify the code and push again.
## 6. Further changes after review
If we have not passed the review, don't be discouraged. Usually a commit needs to be reviewed several times before being accepted! Please follow the review comments and make further changes.
After the further changes, we submit them to the local repo:
```shell
# commit all updated files in a new commit,
# please feel free to enter any appropriate commit message, note that
# we will squash all commits in the pull request as one commit when
# merging into the master branch.
git commit -a
```
> If there are conflicts that prevent the code from being merged, we need to rebase on master branch:
>
> ```shell
> # synchronize the latest code
> git checkout master
> git pull hugegraph
> # rebase on master
> git checkout bugfix-branch
> git rebase -i master
> ```
And push it to GitHub fork repo again:
```shell
# force push the local commit to fork repo
git push -f origin bugfix-branch:bugfix-branch
```
GitHub will automatically update the Pull Request after we push it, wait for code review.
For Any question, please contact us through [dev@hugegraph.apache.org](mailto:dev@hugegraph.apache.org) ([subscriber](https://hugegraph.apache.org/docs/contribution-guidelines/subscribe/) only)

View File

@ -1,7 +0,0 @@
Apache HugeGraph (incubating) is an effort undergoing incubation at The Apache Software Foundation (ASF), sponsored by the Apache Incubator PMC.
Incubation is required of all newly accepted projects until a further review indicates that the infrastructure, communications,
and decision making process have stabilized in a manner consistent with other successful ASF projects.
While incubation status is not necessarily a reflection of the completeness or stability of the code,
it does indicate that the project has yet to be fully endorsed by the ASF.

18
LICENSE
View File

@ -1,4 +1,4 @@
Apache License
Apache License
Version 2.0, January 2004
http://www.apache.org/licenses/
@ -200,19 +200,3 @@
See the License for the specific language governing permissions and
limitations under the License.
========================================================================
Apache 2.0 licenses
========================================================================
The following components are provided under the Apache License. See project link for details.
The text of each license is the standard Apache 2.0 license.
hugegraph-server/hugegraph-test/src/main/java/org/apache/hugegraph/tinkerpop/StructureBasicSuite.java from https://github.com/apache/tinkerpop
hugegraph-server/hugegraph-test/src/main/java/org/apache/hugegraph/tinkerpop/ProcessBasicSuite.java from https://github.com/apache/tinkerpop
hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/backend/id/SnowflakeIdGenerator.java from https://github.com/twitter-archive/snowflake
hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/traversal/optimize/HugeScriptTraversal.java from https://github.com/apache/tinkerpop
hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/type/Nameable.java from https://github.com/JanusGraph/janusgraph
hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/type/define/Cardinality.java from https://github.com/JanusGraph/janusgraph
hugegraph-server/hugegraph-core/src/main/java/org/apache/hugegraph/util/StringEncoding.java from https://github.com/JanusGraph/janusgraph
hugegraph-server/hugegraph-api/src/main/java/org/apache/hugegraph/opencypher/CypherOpProcessor.java from https://github.com/opencypher/cypher-for-gremlin
hugegraph-server/hugegraph-api/src/main/java/org/apache/hugegraph/opencypher/CypherPlugin.java from https://github.com/opencypher/cypher-for-gremlin

55
NOTICE
View File

@ -1,55 +0,0 @@
Apache HugeGraph(incubating)
Copyright 2022-2024 The Apache Software Foundation
This product includes software developed at
The Apache Software Foundation (http://www.apache.org/).
The initial codebase was donated to the ASF by HugeGraph Authors, copyright 2017-2021.
-----------------------------------------------------------------------
This product contains code form the Apache TinkerPop Project:
-----------------------------------------------------------------------
Apache TinkerPop
Copyright 2015-2022 The Apache Software Foundation.
------------------------------------------------------------------------
Activiti
------------------------------------------------------------------------
Activiti BPM Platform
Copyright 2010-2014 Alfresco Software, Ltd.
gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/structure/io/graphml/GraphMLWriterHelper.java
contains DelegatingXMLStreamWriter.java and IndentingXMLStreamWriter.java from
https://github.com/Activiti/Activiti/tree/activiti-5.16/modules/activiti-bpmn-converter/src/main/java/org/activiti/bpmn/converter
------------------------------------------------------------------------
Apache Kerby
------------------------------------------------------------------------
Apache Kerby
Copyright 2015-2017 The Apache Software Foundation
gremlin-server/src/main/java/org/apache/tinkerpop/gremlin/server/auth/JaasKrbUtil.java
from
https://github.com/apache/directory-kerby/blob/kerby-all-1.0.0/kerby-kerb/kerb-simplekdc/src/main/java/org/apache/kerby/kerberos/kerb/client/JaasKrbUtil.java
-----------------------------------------------------------------------
This product contains code form the JanusGraph Project:
-----------------------------------------------------------------------
==============================================================
JanusGraph: Distributed Graph Database
Copyright 2012 with JanusGraph Authors
==============================================================
This product includes software developed by JanusGraph contributors listed
in CONTRIBUTORS.txt; JanusGraph copyright holders are listed in AUTHORS.txt.
This product is based on Titan, originally developed by Aurelius (acquired by
DataStax) and the following individuals:
* Matthias Broecheler
* Dan LaRocque
* Marko A. Rodriguez
* Stephen Mallette
* Pavel Yaskevich

View File

@ -1,98 +1,30 @@
<h1 align="center">
<img width="720" alt="hugegraph-logo" src="https://github.com/apache/incubator-hugegraph/assets/38098239/e02ffaed-4562-486b-ba8f-e68d02bb0ea6" style="zoom:100%;" />
</h1>
<h3 align="center">A graph database that supports more than 10 billion data, high performance and scalability</h3>
<div align="center">
# HugeGraph
[![License](https://img.shields.io/badge/license-Apache%202-0E78BA.svg)](https://www.apache.org/licenses/LICENSE-2.0.html)
[![HugeGraph-CI](https://github.com/apache/incubator-hugegraph/actions/workflows/ci.yml/badge.svg)](https://github.com/apache/incubator-hugegraph/actions/workflows/ci.yml)
[![License checker](https://github.com/apache/incubator-hugegraph/actions/workflows/licence-checker.yml/badge.svg)](https://github.com/apache/incubator-hugegraph/actions/workflows/licence-checker.yml)
[![GitHub Releases Downloads](https://img.shields.io/github/downloads/apache/hugegraph/total.svg)](https://github.com/apache/hugegraph/releases)
</div>
## What is Apache HugeGraph?
[HugeGraph](https://hugegraph.apache.org/) is a fast-speed and highly-scalable [graph database](https://en.wikipedia.org/wiki/Graph_database).
Billions of vertices and edges can be easily stored into and queried from HugeGraph due to its excellent OLTP ability.
As compliance to [Apache TinkerPop 3](https://tinkerpop.apache.org/) framework, various complicated graph queries can be
achieved through [Gremlin](https://tinkerpop.apache.org/gremlin.html)(a powerful graph traversal language).
[![Build Status](https://travis-ci.org/hugegraph/hugegraph.svg?branch=release-0.7)](https://travis-ci.org/hugegraph/hugegraph)
[![codecov](https://codecov.io/gh/hugegraph/hugegraph/branch/release-0.7/graph/badge.svg)](https://codecov.io/gh/hugegraph/hugegraph)
HugeGraph is a fast-speed and highly-scalable [graph database](https://en.wikipedia.org/wiki/Graph_database). Billions of vertices and edges can be easily stored into and queried from HugeGraph due to its excellent OLTP ability. As compliance to [Apache TinkerPop 3](https://tinkerpop.apache.org/) framework, various complicated graph queries can be accomplished through [Gremlin](https://tinkerpop.apache.org/gremlin.html)(a powerful graph traversal language).
## Features
- Compliance to [Apache TinkerPop 3](https://tinkerpop.apache.org/), support [Gremlin](https://tinkerpop.apache.org/gremlin.html) & [Cypher](https://en.wikipedia.org/wiki/Cypher) language
- Compliance to [Apache TinkerPop 3](https://tinkerpop.apache.org/), supporting [Gremlin](https://tinkerpop.apache.org/gremlin.html)
- Schema Metadata Management, including VertexLabel, EdgeLabel, PropertyKey and IndexLabel
- Multi-type Indexes, supporting exact query, range query and complex conditions combination query
- Plug-in Backend Store Driver Framework, support `RocksDB`, `Cassandra`, `HBase`, `ScyllaDB`, and `MySQL/Postgre` now and easy to add another backend store driver if needed
- Integration with `Flink/Spark/HDFS`, and friendly to connect other big data platforms
- Multi-type Indexes, supporting exact query, range query and complex conditons combination query
- Plug-in Backend Store Driver Framework, supporting RocksDB, Cassandra, ScyllaDB and MySQL now and easy to add other backend store driver if needed
- Integration with Hadoop/Spark
## Learn More
## Quick Start
### 1. Docker Way (Convenient for Test)
We can use `docker run -itd --name=graph -p 8080:8080 hugegraph/hugegraph` to quickly start an inner
HugeGraph server with `RocksDB` (in backgrounds) for **test/dev**.
You can visit [doc page](https://hugegraph.apache.org/docs/quickstart/hugegraph-server/#3-deploy) or
the [README](hugegraph-server/hugegraph-dist/docker/README.md) for more details. ([Docker Compose](./hugegraph-server/hugegraph-dist/docker/example))
> Note:
>
> 1. The docker image of hugegraph is a convenience release, but not **official distribution** artifacts. You can find more details from [ASF Release Distribution Policy](https://infra.apache.org/release-distribution.html#dockerhub).
>
> 2. Recommend to use `release tag`(like `1.2.0`) for the stable version. Use `latest` tag to experience the newest functions in development.
### 2. Download Way
Visit [Download Page](https://hugegraph.apache.org/docs/download/download/) and refer the [doc](https://hugegraph.apache.org/docs/quickstart/hugegraph-server/#32-download-the-binary-tar-tarball)
to download the latest release package and start the server.
### 3. Source Building Way
Visit [Source Building Page](https://hugegraph.apache.org/docs/quickstart/hugegraph-server/#33-source-code-compilation) and follow the
steps to build the source code and start the server.
The project [doc page](https://hugegraph.apache.org/docs/) contains more information on HugeGraph
and provides detailed documentation for users. (Structure / Usage / API / Configs...)
And here are links of other **HugeGraph** component/repositories:
1. [hugegraph-toolchain](https://github.com/apache/hugegraph-toolchain) (graph tools **[loader](https://github.com/apache/incubator-hugegraph-toolchain/tree/master/hugegraph-loader)/[dashboard](https://github.com/apache/incubator-hugegraph-toolchain/tree/master/hugegraph-hubble)/[tool](https://github.com/apache/incubator-hugegraph-toolchain/tree/master/hugegraph-tools)/[client](https://github.com/apache/incubator-hugegraph-toolchain/tree/master/hugegraph-client)**)
2. [hugegraph-computer](https://github.com/apache/hugegraph-computer) (integrated **graph computing** system)
3. [hugegraph-commons](https://github.com/apache/hugegraph-commons) (**common & rpc** libs)
4. [hugegraph-website](https://github.com/apache/hugegraph-doc) (**doc & website** code)
5. [hugegraph-ai](https://github.com/apache/incubator-hugegraph-ai) (integrated **Graph AI/LLM/KG** system)
The [project homepage](https://hugegraph.github.io/hugegraph-doc/) contains more information on HugeGraph and provides links to documentation, getting-started guides and release downloads.
## License
HugeGraph is licensed under [Apache 2.0 License](LICENSE).
## Contributing
- Welcome to contribute to HugeGraph, please see [`How to Contribute`](CONTRIBUTING.md) & [Guidelines](https://hugegraph.apache.org/docs/contribution-guidelines/) for more information.
- Note: It's recommended to use [GitHub Desktop](https://desktop.github.com/) to greatly simplify the PR and commit process.
- Thank you to all the people who already contributed to HugeGraph!
[![contributors graph](https://contrib.rocks/image?repo=apache/hugegraph)](https://github.com/apache/incubator-hugegraph/graphs/contributors)
HugeGraph is licensed under Apache 2.0 License.
## Thanks
HugeGraph relies on the [TinkerPop](http://tinkerpop.apache.org) framework, we refer to the storage structure of Titan and the schema definition of DataStax.
Thanks to TinkerPop, thanks to Titan, thanks to DataStax. Thanks to all other organizations or authors who contributed to the project.
You are welcome to contribute to HugeGraph,
and we are looking forward to working with you to build an excellent open-source community.
## Contact Us
- [GitHub Issues](https://github.com/apache/incubator-hugegraph/issues): Feedback on usage issues and functional requirements (quick response)
- Feedback Email: [dev@hugegraph.apache.org](mailto:dev@hugegraph.apache.org) ([subscriber](https://hugegraph.apache.org/docs/contribution-guidelines/subscribe/) only)
- WeChat public account: Apache HugeGraph, welcome to scan this QR code to follow us.
<img src="https://github.com/apache/incubator-hugegraph-doc/blob/master/assets/images/wechat.png?raw=true" alt="QR png" width="300"/>
HugeGraph relies on the [TinkerPop](http://tinkerpop.apache.org) framework, we refer to the storage structure of [JanusGraph](http://janusgraph.org) and the schema definition of [DataStax](https://www.datastax.com).
Thanks to Tinkerpop, thanks to JanusGraph and Titan, thanks to DataStax. Thanks to all other organizations or authors who contributed to the project.
You are welcome to contribute to HugeGraph, and we hope to work with you to create a better open source environment.

View File

@ -20,4 +20,5 @@ export MAVEN_HOME=/home/scmtools/buildkit/maven/apache-maven-3.3.9/
export JAVA_HOME=/home/scmtools/buildkit/java/jdk1.8.0_25/
export PATH=$JAVA_HOME/bin:$MAVEN_HOME/bin:$PATH
mvn clean test -Dtest=UnitTestSuite
mvn clean compile

View File

@ -1,63 +0,0 @@
#
# 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.
#
spring:
application:
name: hugegraph-pd
management:
metrics:
export:
prometheus:
enabled: true
endpoints:
web:
exposure:
include: "*"
logging:
config: 'file:./conf/log4j2.xml'
license:
verify-path: ./conf/verify-license.json
license-path: ./conf/hugegraph.license
grpc:
port: 8686
host: 127.0.0.1
server:
port: 8620
pd:
data-path: ./pd_data
patrol-interval: 1800
initial-store-count: 3
initial-store-list: 127.0.0.1:8500,127.0.0.1:8501,127.0.0.1:8502
raft:
address: 127.0.0.1:8610
peers-list: 127.0.0.1:8610,127.0.0.1:8611,127.0.0.1:8612
store:
max-down-time: 172800
monitor_data_enabled: true
monitor_data_interval: 1 minute
monitor_data_retention: 1 day
initial-store-count: 1
partition:
default-shard-count: 1
store-max-shard-count: 12

View File

@ -1,63 +0,0 @@
#
# 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.
#
spring:
application:
name: hugegraph-pd
management:
metrics:
export:
prometheus:
enabled: true
endpoints:
web:
exposure:
include: "*"
logging:
config: 'file:./conf/log4j2.xml'
license:
verify-path: ./conf/verify-license.json
license-path: ./conf/hugegraph.license
grpc:
port: 8687
host: 127.0.0.1
server:
port: 8621
pd:
data-path: ./pd_data
patrol-interval: 1800
initial-store-count: 3
initial-store-list: 127.0.0.1:8500,127.0.0.1:8501,127.0.0.1:8502
raft:
address: 127.0.0.1:8611
peers-list: 127.0.0.1:8610,127.0.0.1:8611,127.0.0.1:8612
store:
max-down-time: 172800
monitor_data_enabled: true
monitor_data_interval: 1 minute
monitor_data_retention: 1 day
initial-store-count: 1
partition:
default-shard-count: 1
store-max-shard-count: 12

View File

@ -1,63 +0,0 @@
#
# 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.
#
spring:
application:
name: hugegraph-pd
management:
metrics:
export:
prometheus:
enabled: true
endpoints:
web:
exposure:
include: "*"
logging:
config: 'file:./conf/log4j2.xml'
license:
verify-path: ./conf/verify-license.json
license-path: ./conf/hugegraph.license
grpc:
port: 8688
host: 127.0.0.1
server:
port: 8622
pd:
data-path: ./pd_data
patrol-interval: 1800
initial-store-count: 3
initial-store-list: 127.0.0.1:8500,127.0.0.1:8501,127.0.0.1:8502
raft:
address: 127.0.0.1:8612
peers-list: 127.0.0.1:8610,127.0.0.1:8611,127.0.0.1:8612
store:
max-down-time: 172800
monitor_data_enabled: true
monitor_data_interval: 1 minute
monitor_data_retention: 1 day
initial-store-count: 1
partition:
default-shard-count: 1
store-max-shard-count: 12

View File

@ -1,57 +0,0 @@
#
# 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.
#
pdserver:
address: 127.0.0.1:8686,127.0.0.1:8687,127.0.0.1:8688
management:
metrics:
export:
prometheus:
enabled: true
endpoints:
web:
exposure:
include: "*"
grpc:
host: 127.0.0.1
port: 8500
netty-server:
max-inbound-message-size: 1000MB
raft:
disruptorBufferSize: 1024
address: 127.0.0.1:8510
max-log-file-size: 600000000000
snapshotInterval: 1800
server:
port: 8520
app:
data-path: ./storage
spring:
application:
name: store-node-grpc-server
profiles:
active: default
include: pd
logging:
config: 'file:./conf/log4j2.xml'
level:
root: info

View File

@ -1,57 +0,0 @@
#
# 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.
#
pdserver:
address: 127.0.0.1:8686,127.0.0.1:8687,127.0.0.1:8688
management:
metrics:
export:
prometheus:
enabled: true
endpoints:
web:
exposure:
include: "*"
grpc:
host: 127.0.0.1
port: 8501
netty-server:
max-inbound-message-size: 1000MB
raft:
disruptorBufferSize: 1024
address: 127.0.0.1:8511
max-log-file-size: 600000000000
snapshotInterval: 1800
server:
port: 8521
app:
data-path: ./storage
spring:
application:
name: store-node-grpc-server
profiles:
active: default
include: pd
logging:
config: 'file:./conf/log4j2.xml'
level:
root: info

View File

@ -1,57 +0,0 @@
#
# 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.
#
pdserver:
address: 127.0.0.1:8686,127.0.0.1:8687,127.0.0.1:8688
management:
metrics:
export:
prometheus:
enabled: true
endpoints:
web:
exposure:
include: "*"
grpc:
host: 127.0.0.1
port: 8502
netty-server:
max-inbound-message-size: 1000MB
raft:
disruptorBufferSize: 1024
address: 127.0.0.1:8512
max-log-file-size: 600000000000
snapshotInterval: 1800
server:
port: 8522
app:
data-path: ./storage
spring:
application:
name: store-node-grpc-server
profiles:
active: default
include: pd
logging:
config: 'file:./conf/log4j2.xml'
level:
root: info

View File

@ -1,19 +0,0 @@
# auth config: org.apache.hugegraph.auth.HugeFactoryAuthProxy
gremlin.graph=org.apache.hugegraph.HugeFactory
# cache config
vertex.cache_type=l2
edge.cache_type=l2
store=hugegraph
backend=hstore
serializer=binary
# pd config
pd.peers=127.0.0.1:8686,127.0.0.1:8687,127.0.0.1:8688
# task config
task.scheduler_type=local
task.schedule_period=10
task.retry=0
task.wait_timeout=10

View File

@ -1,25 +0,0 @@
#
# 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.
#
hosts: [localhost]
port: 8181
serializer: {
className: org.apache.tinkerpop.gremlin.driver.ser.GraphSONMessageSerializerV1d0,
config: {
serializeResultToString: false,
ioRegistries: [org.apache.hugegraph.io.HugeGraphIoRegistry]
}
}

View File

@ -1,127 +0,0 @@
#
# 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.
#
# host and port of gremlin server, need to be consistent with host and port in rest-server.properties
host: 127.0.0.1
port: 8181
# timeout in ms of gremlin query
evaluationTimeout: 30000
channelizer: org.apache.tinkerpop.gremlin.server.channel.WsAndHttpChannelizer
# don't set graph at here, this happens after support for dynamically adding graph
graphs: {
}
scriptEngines: {
gremlin-groovy: {
staticImports: [
org.opencypher.gremlin.process.traversal.CustomPredicates.*',
org.opencypher.gremlin.traversal.CustomFunctions.*
],
plugins: {
org.apache.hugegraph.plugin.HugeGraphGremlinPlugin: {},
org.apache.tinkerpop.gremlin.server.jsr223.GremlinServerGremlinPlugin: {},
org.apache.tinkerpop.gremlin.jsr223.ImportGremlinPlugin: {
classImports: [
java.lang.Math,
org.apache.hugegraph.backend.id.IdGenerator,
org.apache.hugegraph.type.define.Directions,
org.apache.hugegraph.type.define.NodeRole,
org.apache.hugegraph.masterelection.GlobalMasterInfo,
org.apache.hugegraph.util.DateUtil,
org.apache.hugegraph.traversal.algorithm.CollectionPathsTraverser,
org.apache.hugegraph.traversal.algorithm.CountTraverser,
org.apache.hugegraph.traversal.algorithm.CustomizedCrosspointsTraverser,
org.apache.hugegraph.traversal.algorithm.CustomizePathsTraverser,
org.apache.hugegraph.traversal.algorithm.FusiformSimilarityTraverser,
org.apache.hugegraph.traversal.algorithm.HugeTraverser,
org.apache.hugegraph.traversal.algorithm.JaccardSimilarTraverser,
org.apache.hugegraph.traversal.algorithm.KneighborTraverser,
org.apache.hugegraph.traversal.algorithm.KoutTraverser,
org.apache.hugegraph.traversal.algorithm.MultiNodeShortestPathTraverser,
org.apache.hugegraph.traversal.algorithm.NeighborRankTraverser,
org.apache.hugegraph.traversal.algorithm.PathsTraverser,
org.apache.hugegraph.traversal.algorithm.PersonalRankTraverser,
org.apache.hugegraph.traversal.algorithm.SameNeighborTraverser,
org.apache.hugegraph.traversal.algorithm.ShortestPathTraverser,
org.apache.hugegraph.traversal.algorithm.SingleSourceShortestPathTraverser,
org.apache.hugegraph.traversal.algorithm.SubGraphTraverser,
org.apache.hugegraph.traversal.algorithm.TemplatePathsTraverser,
org.apache.hugegraph.traversal.algorithm.steps.EdgeStep,
org.apache.hugegraph.traversal.algorithm.steps.RepeatEdgeStep,
org.apache.hugegraph.traversal.algorithm.steps.WeightedEdgeStep,
org.apache.hugegraph.traversal.optimize.ConditionP,
org.apache.hugegraph.traversal.optimize.Text,
org.apache.hugegraph.traversal.optimize.TraversalUtil,
org.opencypher.gremlin.traversal.CustomFunctions,
org.opencypher.gremlin.traversal.CustomPredicate
],
methodImports: [
java.lang.Math#*,
org.opencypher.gremlin.traversal.CustomPredicate#*,
org.opencypher.gremlin.traversal.CustomFunctions#*
]
},
org.apache.tinkerpop.gremlin.jsr223.ScriptFileGremlinPlugin: {
files: [scripts/empty-sample.groovy]
}
}
}
}
serializers:
- {className: org.apache.tinkerpop.gremlin.driver.ser.GraphBinaryMessageSerializerV1,
config: {
serializeResultToString: false,
ioRegistries: [org.apache.hugegraph.io.HugeGraphIoRegistry]
}
}
- {className: org.apache.tinkerpop.gremlin.driver.ser.GraphSONMessageSerializerV1d0,
config: {
serializeResultToString: false,
ioRegistries: [org.apache.hugegraph.io.HugeGraphIoRegistry]
}
}
- {className: org.apache.tinkerpop.gremlin.driver.ser.GraphSONMessageSerializerV2d0,
config: {
serializeResultToString: false,
ioRegistries: [org.apache.hugegraph.io.HugeGraphIoRegistry]
}
}
- {className: org.apache.tinkerpop.gremlin.driver.ser.GraphSONMessageSerializerV3d0,
config: {
serializeResultToString: false,
ioRegistries: [org.apache.hugegraph.io.HugeGraphIoRegistry]
}
}
metrics: {
consoleReporter: {enabled: false, interval: 180000},
csvReporter: {enabled: false, interval: 180000, fileName: ./metrics/gremlin-server-metrics.csv},
jmxReporter: {enabled: false},
slf4jReporter: {enabled: false, interval: 180000},
gangliaReporter: {enabled: false, interval: 180000, addressingMode: MULTICAST},
graphiteReporter: {enabled: false, interval: 180000}
}
maxInitialLineLength: 4096
maxHeaderSize: 8192
maxChunkSize: 8192
maxContentLength: 65536
maxAccumulationBufferComponents: 1024
resultIterationBatchSize: 64
writeBufferLowWaterMark: 32768
writeBufferHighWaterMark: 65536
ssl: {
enabled: false
}

View File

@ -1,144 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<!--
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.
-->
<!-- Config will be auto loaded every 60s -->
<configuration status="error" monitorInterval="60">
<properties>
<property name="LOG_PATH">logs</property>
<property name="FILE_NAME">hugegraph-server</property>
</properties>
<appenders>
<Console name="console" target="SYSTEM_OUT">
<ThresholdFilter level="DEBUG" onMatch="ACCEPT" onMismatch="DENY"/>
<PatternLayout pattern="%-d{yyyy-MM-dd HH:mm:ss} [%t] [%p] %c{1.} - %m%n"/>
</Console>
<!-- Normal server log config -->
<RollingRandomAccessFile name="file" fileName="${LOG_PATH}/${FILE_NAME}.log"
filePattern="${LOG_PATH}/$${date:yyyy-MM}/${FILE_NAME}-%d{yyyy-MM-dd}-%i.log"
immediateFlush="false">
<ThresholdFilter level="TRACE" onMatch="ACCEPT" onMismatch="DENY"/>
<PatternLayout pattern="%-d{yyyy-MM-dd HH:mm:ss} [%t] [%p] %c{1.} - %m%n"/>
<!-- Trigger after exceeding 1day or 50MB -->
<Policies>
<SizeBasedTriggeringPolicy size="50MB"/>
<TimeBasedTriggeringPolicy interval="1" modulate="true"/>
</Policies>
<!-- Keep 5 files per day & auto delete after over 2GB or 100 files -->
<DefaultRolloverStrategy max="5">
<Delete basePath="${LOG_PATH}" maxDepth="2">
<IfFileName glob="*/*.log"/>
<!-- Limit log amount & size -->
<IfAny>
<IfAccumulatedFileSize exceeds="2GB"/>
<IfAccumulatedFileCount exceeds="100"/>
</IfAny>
</Delete>
</DefaultRolloverStrategy>
</RollingRandomAccessFile>
<!-- Separate & compress audit log, buffer size is 512KB -->
<RollingRandomAccessFile name="audit" fileName="${LOG_PATH}/audit-${FILE_NAME}.log"
filePattern="${LOG_PATH}/$${date:yyyy-MM}/audit-${FILE_NAME}-%d{yyyy-MM-dd-HH}-%i.gz"
bufferSize="524288" immediateFlush="false">
<ThresholdFilter level="TRACE" onMatch="ACCEPT" onMismatch="DENY"/>
<!-- Use simple format for audit log to speed up -->
<PatternLayout pattern="%-d{yyyy-MM-dd HH:mm:ss} - %m%n"/>
<!-- Trigger after exceeding 1hour or 500MB -->
<Policies>
<SizeBasedTriggeringPolicy size="500MB"/>
<TimeBasedTriggeringPolicy interval="1" modulate="true"/>
</Policies>
<!-- Keep 2 files per hour & auto delete [after 60 days] or [over 5GB or 500 files] -->
<DefaultRolloverStrategy max="2">
<Delete basePath="${LOG_PATH}" maxDepth="2">
<IfFileName glob="*/*.gz"/>
<IfLastModified age="60d"/>
<IfAny>
<IfAccumulatedFileSize exceeds="5GB"/>
<IfAccumulatedFileCount exceeds="500"/>
</IfAny>
</Delete>
</DefaultRolloverStrategy>
</RollingRandomAccessFile>
<!-- Slow query log config -->
<RollingRandomAccessFile name="slowQueryLog" fileName="${LOG_PATH}/slow_query.log"
filePattern="${LOG_PATH}/$${date:yyyy-MM}/slow_query_log-%d{yyyy-MM-dd}-%i.log"
immediateFlush="false">
<ThresholdFilter level="TRACE" onMatch="ACCEPT" onMismatch="DENY"/>
<PatternLayout pattern="%-d{yyyy-MM-dd HH:mm:ss} [%t] [%p] %c{1.} - %m%n"/>
<!-- Trigger after exceeding 1day or 50MB -->
<Policies>
<SizeBasedTriggeringPolicy size="50MB"/>
<TimeBasedTriggeringPolicy interval="1" modulate="true"/>
</Policies>
<!-- Keep 5 files per day & auto delete after over 2GB or 100 files -->
<DefaultRolloverStrategy max="5">
<Delete basePath="${LOG_PATH}" maxDepth="2">
<IfFileName glob="*/*.log"/>
<!-- Limit log amount & size -->
<IfAny>
<IfAccumulatedFileSize exceeds="2GB"/>
<IfAccumulatedFileCount exceeds="100"/>
</IfAny>
</Delete>
</DefaultRolloverStrategy>
</RollingRandomAccessFile>
</appenders>
<loggers>
<root level="INFO">
<appender-ref ref="file"/>
</root>
<logger name="org.apache.cassandra" level="INFO" additivity="false">
<appender-ref ref="file"/>
</logger>
<logger name="org.apache.hadoop" level="INFO" additivity="false">
<appender-ref ref="file"/>
</logger>
<logger name="org.apache.zookeeper" level="WARN" additivity="false">
<appender-ref ref="file"/>
</logger>
<logger name="com.datastax.driver" level="WARN" additivity="false">
<appender-ref ref="file"/>
</logger>
<logger name="com.alipay.sofa" level="WARN" additivity="false">
<appender-ref ref="file"/>
</logger>
<logger name="io.netty" level="INFO" additivity="false">
<appender-ref ref="file"/>
</logger>
<logger name="org.apache.commons" level="INFO" additivity="false">
<appender-ref ref="file"/>
</logger>
<!-- Use mixed async way to output logs -->
<AsyncLogger name="org.apache.hugegraph" level="INFO" additivity="false">
<appender-ref ref="file"/>
</AsyncLogger>
<AsyncLogger name="org.apache.hugegraph.auth" level="INFO" additivity="false">
<appender-ref ref="audit"/>
</AsyncLogger>
<AsyncLogger name="org.apache.hugegraph.api.filter.AuthenticationFilter" level="INFO" additivity="false">
<appender-ref ref="audit"/>
</AsyncLogger>
<AsyncLogger name="org.apache.hugegraph.api.filter.AccessLogFilter" level="INFO" additivity="false">
<appender-ref ref="slowQueryLog"/>
</AsyncLogger>
</loggers>
</configuration>

View File

@ -1,30 +0,0 @@
#
# 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.
#
hosts: [localhost]
port: 8181
serializer: {
className: org.apache.tinkerpop.gremlin.driver.ser.GraphSONMessageSerializerV1d0,
config: {
serializeResultToString: false,
# The duplication of HugeGraphIoRegistry is meant to fix a bug in the
# 'org.apache.tinkerpop.gremlin.driver.Settings:from(Configuration)' method.
ioRegistries: [
org.apache.hugegraph.io.HugeGraphIoRegistry,
org.apache.hugegraph.io.HugeGraphIoRegistry
]
}
}

View File

@ -1,25 +0,0 @@
#
# 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.
#
hosts: [localhost]
port: 8181
serializer: {
className: org.apache.tinkerpop.gremlin.driver.ser.GraphSONMessageSerializerV1d0,
config: {
serializeResultToString: false,
ioRegistries: [org.apache.hugegraph.io.HugeGraphIoRegistry]
}
}

View File

@ -1,28 +0,0 @@
# bind url
restserver.url=http://127.0.0.1:8081
# gremlin server url, need to be consistent with host and port in gremlin-server.yaml
gremlinserver.url=http://127.0.0.1:8181
graphs=./conf/graphs
# configuration of arthas
arthas.telnet_port=8562
arthas.http_port=8561
arthas.ip=127.0.0.1
arthas.disabled_commands=jad
# authentication configs
# choose 'org.apache.hugegraph.auth.StandardAuthenticator' or
# 'org.apache.hugegraph.auth.ConfigAuthenticator'
#auth.authenticator=
# rpc server configs for multi graph-servers or raft-servers
rpc.server_host=127.0.0.1
rpc.server_port=8091
# lightweight load balancing (beta)
server.id=server-1
server.role=master
# slow query log
log.slow_query_threshold=1000

View File

@ -1,19 +0,0 @@
# auth config: org.apache.hugegraph.auth.HugeFactoryAuthProxy
gremlin.graph=org.apache.hugegraph.HugeFactory
# cache config
vertex.cache_type=l2
edge.cache_type=l2
store=hugegraph
backend=hstore
serializer=binary
# pd config
pd.peers=127.0.0.1:8686,127.0.0.1:8687,127.0.0.1:8688
# task config
task.scheduler_type=local
task.schedule_period=10
task.retry=0
task.wait_timeout=10

View File

@ -1,25 +0,0 @@
#
# 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.
#
hosts: [localhost]
port: 8182
serializer: {
className: org.apache.tinkerpop.gremlin.driver.ser.GraphSONMessageSerializerV1d0,
config: {
serializeResultToString: false,
ioRegistries: [org.apache.hugegraph.io.HugeGraphIoRegistry]
}
}

View File

@ -1,127 +0,0 @@
#
# 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.
#
# host and port of gremlin server, need to be consistent with host and port in rest-server.properties
host: 127.0.0.1
port: 8182
# timeout in ms of gremlin query
evaluationTimeout: 30000
channelizer: org.apache.tinkerpop.gremlin.server.channel.WsAndHttpChannelizer
# don't set graph at here, this happens after support for dynamically adding graph
graphs: {
}
scriptEngines: {
gremlin-groovy: {
staticImports: [
org.opencypher.gremlin.process.traversal.CustomPredicates.*',
org.opencypher.gremlin.traversal.CustomFunctions.*
],
plugins: {
org.apache.hugegraph.plugin.HugeGraphGremlinPlugin: {},
org.apache.tinkerpop.gremlin.server.jsr223.GremlinServerGremlinPlugin: {},
org.apache.tinkerpop.gremlin.jsr223.ImportGremlinPlugin: {
classImports: [
java.lang.Math,
org.apache.hugegraph.backend.id.IdGenerator,
org.apache.hugegraph.type.define.Directions,
org.apache.hugegraph.type.define.NodeRole,
org.apache.hugegraph.masterelection.GlobalMasterInfo,
org.apache.hugegraph.util.DateUtil,
org.apache.hugegraph.traversal.algorithm.CollectionPathsTraverser,
org.apache.hugegraph.traversal.algorithm.CountTraverser,
org.apache.hugegraph.traversal.algorithm.CustomizedCrosspointsTraverser,
org.apache.hugegraph.traversal.algorithm.CustomizePathsTraverser,
org.apache.hugegraph.traversal.algorithm.FusiformSimilarityTraverser,
org.apache.hugegraph.traversal.algorithm.HugeTraverser,
org.apache.hugegraph.traversal.algorithm.JaccardSimilarTraverser,
org.apache.hugegraph.traversal.algorithm.KneighborTraverser,
org.apache.hugegraph.traversal.algorithm.KoutTraverser,
org.apache.hugegraph.traversal.algorithm.MultiNodeShortestPathTraverser,
org.apache.hugegraph.traversal.algorithm.NeighborRankTraverser,
org.apache.hugegraph.traversal.algorithm.PathsTraverser,
org.apache.hugegraph.traversal.algorithm.PersonalRankTraverser,
org.apache.hugegraph.traversal.algorithm.SameNeighborTraverser,
org.apache.hugegraph.traversal.algorithm.ShortestPathTraverser,
org.apache.hugegraph.traversal.algorithm.SingleSourceShortestPathTraverser,
org.apache.hugegraph.traversal.algorithm.SubGraphTraverser,
org.apache.hugegraph.traversal.algorithm.TemplatePathsTraverser,
org.apache.hugegraph.traversal.algorithm.steps.EdgeStep,
org.apache.hugegraph.traversal.algorithm.steps.RepeatEdgeStep,
org.apache.hugegraph.traversal.algorithm.steps.WeightedEdgeStep,
org.apache.hugegraph.traversal.optimize.ConditionP,
org.apache.hugegraph.traversal.optimize.Text,
org.apache.hugegraph.traversal.optimize.TraversalUtil,
org.opencypher.gremlin.traversal.CustomFunctions,
org.opencypher.gremlin.traversal.CustomPredicate
],
methodImports: [
java.lang.Math#*,
org.opencypher.gremlin.traversal.CustomPredicate#*,
org.opencypher.gremlin.traversal.CustomFunctions#*
]
},
org.apache.tinkerpop.gremlin.jsr223.ScriptFileGremlinPlugin: {
files: [scripts/empty-sample.groovy]
}
}
}
}
serializers:
- {className: org.apache.tinkerpop.gremlin.driver.ser.GraphBinaryMessageSerializerV1,
config: {
serializeResultToString: false,
ioRegistries: [org.apache.hugegraph.io.HugeGraphIoRegistry]
}
}
- {className: org.apache.tinkerpop.gremlin.driver.ser.GraphSONMessageSerializerV1d0,
config: {
serializeResultToString: false,
ioRegistries: [org.apache.hugegraph.io.HugeGraphIoRegistry]
}
}
- {className: org.apache.tinkerpop.gremlin.driver.ser.GraphSONMessageSerializerV2d0,
config: {
serializeResultToString: false,
ioRegistries: [org.apache.hugegraph.io.HugeGraphIoRegistry]
}
}
- {className: org.apache.tinkerpop.gremlin.driver.ser.GraphSONMessageSerializerV3d0,
config: {
serializeResultToString: false,
ioRegistries: [org.apache.hugegraph.io.HugeGraphIoRegistry]
}
}
metrics: {
consoleReporter: {enabled: false, interval: 180000},
csvReporter: {enabled: false, interval: 180000, fileName: ./metrics/gremlin-server-metrics.csv},
jmxReporter: {enabled: false},
slf4jReporter: {enabled: false, interval: 180000},
gangliaReporter: {enabled: false, interval: 180000, addressingMode: MULTICAST},
graphiteReporter: {enabled: false, interval: 180000}
}
maxInitialLineLength: 4096
maxHeaderSize: 8192
maxChunkSize: 8192
maxContentLength: 65536
maxAccumulationBufferComponents: 1024
resultIterationBatchSize: 64
writeBufferLowWaterMark: 32768
writeBufferHighWaterMark: 65536
ssl: {
enabled: false
}

View File

@ -1,144 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<!--
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.
-->
<!-- Config will be auto loaded every 60s -->
<configuration status="error" monitorInterval="60">
<properties>
<property name="LOG_PATH">logs</property>
<property name="FILE_NAME">hugegraph-server</property>
</properties>
<appenders>
<Console name="console" target="SYSTEM_OUT">
<ThresholdFilter level="DEBUG" onMatch="ACCEPT" onMismatch="DENY"/>
<PatternLayout pattern="%-d{yyyy-MM-dd HH:mm:ss} [%t] [%p] %c{1.} - %m%n"/>
</Console>
<!-- Normal server log config -->
<RollingRandomAccessFile name="file" fileName="${LOG_PATH}/${FILE_NAME}.log"
filePattern="${LOG_PATH}/$${date:yyyy-MM}/${FILE_NAME}-%d{yyyy-MM-dd}-%i.log"
immediateFlush="false">
<ThresholdFilter level="TRACE" onMatch="ACCEPT" onMismatch="DENY"/>
<PatternLayout pattern="%-d{yyyy-MM-dd HH:mm:ss} [%t] [%p] %c{1.} - %m%n"/>
<!-- Trigger after exceeding 1day or 50MB -->
<Policies>
<SizeBasedTriggeringPolicy size="50MB"/>
<TimeBasedTriggeringPolicy interval="1" modulate="true"/>
</Policies>
<!-- Keep 5 files per day & auto delete after over 2GB or 100 files -->
<DefaultRolloverStrategy max="5">
<Delete basePath="${LOG_PATH}" maxDepth="2">
<IfFileName glob="*/*.log"/>
<!-- Limit log amount & size -->
<IfAny>
<IfAccumulatedFileSize exceeds="2GB"/>
<IfAccumulatedFileCount exceeds="100"/>
</IfAny>
</Delete>
</DefaultRolloverStrategy>
</RollingRandomAccessFile>
<!-- Separate & compress audit log, buffer size is 512KB -->
<RollingRandomAccessFile name="audit" fileName="${LOG_PATH}/audit-${FILE_NAME}.log"
filePattern="${LOG_PATH}/$${date:yyyy-MM}/audit-${FILE_NAME}-%d{yyyy-MM-dd-HH}-%i.gz"
bufferSize="524288" immediateFlush="false">
<ThresholdFilter level="TRACE" onMatch="ACCEPT" onMismatch="DENY"/>
<!-- Use simple format for audit log to speed up -->
<PatternLayout pattern="%-d{yyyy-MM-dd HH:mm:ss} - %m%n"/>
<!-- Trigger after exceeding 1hour or 500MB -->
<Policies>
<SizeBasedTriggeringPolicy size="500MB"/>
<TimeBasedTriggeringPolicy interval="1" modulate="true"/>
</Policies>
<!-- Keep 2 files per hour & auto delete [after 60 days] or [over 5GB or 500 files] -->
<DefaultRolloverStrategy max="2">
<Delete basePath="${LOG_PATH}" maxDepth="2">
<IfFileName glob="*/*.gz"/>
<IfLastModified age="60d"/>
<IfAny>
<IfAccumulatedFileSize exceeds="5GB"/>
<IfAccumulatedFileCount exceeds="500"/>
</IfAny>
</Delete>
</DefaultRolloverStrategy>
</RollingRandomAccessFile>
<!-- Slow query log config -->
<RollingRandomAccessFile name="slowQueryLog" fileName="${LOG_PATH}/slow_query.log"
filePattern="${LOG_PATH}/$${date:yyyy-MM}/slow_query_log-%d{yyyy-MM-dd}-%i.log"
immediateFlush="false">
<ThresholdFilter level="TRACE" onMatch="ACCEPT" onMismatch="DENY"/>
<PatternLayout pattern="%-d{yyyy-MM-dd HH:mm:ss} [%t] [%p] %c{1.} - %m%n"/>
<!-- Trigger after exceeding 1day or 50MB -->
<Policies>
<SizeBasedTriggeringPolicy size="50MB"/>
<TimeBasedTriggeringPolicy interval="1" modulate="true"/>
</Policies>
<!-- Keep 5 files per day & auto delete after over 2GB or 100 files -->
<DefaultRolloverStrategy max="5">
<Delete basePath="${LOG_PATH}" maxDepth="2">
<IfFileName glob="*/*.log"/>
<!-- Limit log amount & size -->
<IfAny>
<IfAccumulatedFileSize exceeds="2GB"/>
<IfAccumulatedFileCount exceeds="100"/>
</IfAny>
</Delete>
</DefaultRolloverStrategy>
</RollingRandomAccessFile>
</appenders>
<loggers>
<root level="INFO">
<appender-ref ref="file"/>
</root>
<logger name="org.apache.cassandra" level="INFO" additivity="false">
<appender-ref ref="file"/>
</logger>
<logger name="org.apache.hadoop" level="INFO" additivity="false">
<appender-ref ref="file"/>
</logger>
<logger name="org.apache.zookeeper" level="WARN" additivity="false">
<appender-ref ref="file"/>
</logger>
<logger name="com.datastax.driver" level="WARN" additivity="false">
<appender-ref ref="file"/>
</logger>
<logger name="com.alipay.sofa" level="WARN" additivity="false">
<appender-ref ref="file"/>
</logger>
<logger name="io.netty" level="INFO" additivity="false">
<appender-ref ref="file"/>
</logger>
<logger name="org.apache.commons" level="INFO" additivity="false">
<appender-ref ref="file"/>
</logger>
<!-- Use mixed async way to output logs -->
<AsyncLogger name="org.apache.hugegraph" level="INFO" additivity="false">
<appender-ref ref="file"/>
</AsyncLogger>
<AsyncLogger name="org.apache.hugegraph.auth" level="INFO" additivity="false">
<appender-ref ref="audit"/>
</AsyncLogger>
<AsyncLogger name="org.apache.hugegraph.api.filter.AuthenticationFilter" level="INFO" additivity="false">
<appender-ref ref="audit"/>
</AsyncLogger>
<AsyncLogger name="org.apache.hugegraph.api.filter.AccessLogFilter" level="INFO" additivity="false">
<appender-ref ref="slowQueryLog"/>
</AsyncLogger>
</loggers>
</configuration>

View File

@ -1,30 +0,0 @@
#
# 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.
#
hosts: [localhost]
port: 8182
serializer: {
className: org.apache.tinkerpop.gremlin.driver.ser.GraphSONMessageSerializerV1d0,
config: {
serializeResultToString: false,
# The duplication of HugeGraphIoRegistry is meant to fix a bug in the
# 'org.apache.tinkerpop.gremlin.driver.Settings:from(Configuration)' method.
ioRegistries: [
org.apache.hugegraph.io.HugeGraphIoRegistry,
org.apache.hugegraph.io.HugeGraphIoRegistry
]
}
}

View File

@ -1,25 +0,0 @@
#
# 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.
#
hosts: [localhost]
port: 8182
serializer: {
className: org.apache.tinkerpop.gremlin.driver.ser.GraphSONMessageSerializerV1d0,
config: {
serializeResultToString: false,
ioRegistries: [org.apache.hugegraph.io.HugeGraphIoRegistry]
}
}

View File

@ -1,26 +0,0 @@
# bind url
restserver.url=http://127.0.0.1:8082
# gremlin server url, need to be consistent with host and port in gremlin-server.yaml
gremlinserver.url=http://127.0.0.1:8182
graphs=./conf/graphs
# configuration of arthas
arthas.telnet_port=8572
arthas.http_port=8571
arthas.ip=127.0.0.1
arthas.disabled_commands=jad
# authentication configs
# choose 'org.apache.hugegraph.auth.StandardAuthenticator' or
# 'org.apache.hugegraph.auth.ConfigAuthenticator'
#auth.authenticator=
# rpc server configs for multi graph-servers or raft-servers
rpc.server_host=127.0.0.1
rpc.server_port=8092
#rpc.server_timeout=30
# lightweight load balancing (beta)
server.id=server-2
server.role=worker

View File

@ -1,19 +0,0 @@
# auth config: org.apache.hugegraph.auth.HugeFactoryAuthProxy
gremlin.graph=org.apache.hugegraph.HugeFactory
# cache config
vertex.cache_type=l2
edge.cache_type=l2
store=hugegraph
backend=hstore
serializer=binary
# pd config
pd.peers=127.0.0.1:8686,127.0.0.1:8687,127.0.0.1:8688
# task config
task.scheduler_type=local
task.schedule_period=10
task.retry=0
task.wait_timeout=10

View File

@ -1,25 +0,0 @@
#
# 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.
#
hosts: [localhost]
port: 8183
serializer: {
className: org.apache.tinkerpop.gremlin.driver.ser.GraphSONMessageSerializerV1d0,
config: {
serializeResultToString: false,
ioRegistries: [org.apache.hugegraph.io.HugeGraphIoRegistry]
}
}

View File

@ -1,127 +0,0 @@
#
# 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.
#
# host and port of gremlin server, need to be consistent with host and port in rest-server.properties
host: 127.0.0.1
port: 8183
# timeout in ms of gremlin query
evaluationTimeout: 30000
channelizer: org.apache.tinkerpop.gremlin.server.channel.WsAndHttpChannelizer
# don't set graph at here, this happens after support for dynamically adding graph
graphs: {
}
scriptEngines: {
gremlin-groovy: {
staticImports: [
org.opencypher.gremlin.process.traversal.CustomPredicates.*',
org.opencypher.gremlin.traversal.CustomFunctions.*
],
plugins: {
org.apache.hugegraph.plugin.HugeGraphGremlinPlugin: {},
org.apache.tinkerpop.gremlin.server.jsr223.GremlinServerGremlinPlugin: {},
org.apache.tinkerpop.gremlin.jsr223.ImportGremlinPlugin: {
classImports: [
java.lang.Math,
org.apache.hugegraph.backend.id.IdGenerator,
org.apache.hugegraph.type.define.Directions,
org.apache.hugegraph.type.define.NodeRole,
org.apache.hugegraph.masterelection.GlobalMasterInfo,
org.apache.hugegraph.util.DateUtil,
org.apache.hugegraph.traversal.algorithm.CollectionPathsTraverser,
org.apache.hugegraph.traversal.algorithm.CountTraverser,
org.apache.hugegraph.traversal.algorithm.CustomizedCrosspointsTraverser,
org.apache.hugegraph.traversal.algorithm.CustomizePathsTraverser,
org.apache.hugegraph.traversal.algorithm.FusiformSimilarityTraverser,
org.apache.hugegraph.traversal.algorithm.HugeTraverser,
org.apache.hugegraph.traversal.algorithm.JaccardSimilarTraverser,
org.apache.hugegraph.traversal.algorithm.KneighborTraverser,
org.apache.hugegraph.traversal.algorithm.KoutTraverser,
org.apache.hugegraph.traversal.algorithm.MultiNodeShortestPathTraverser,
org.apache.hugegraph.traversal.algorithm.NeighborRankTraverser,
org.apache.hugegraph.traversal.algorithm.PathsTraverser,
org.apache.hugegraph.traversal.algorithm.PersonalRankTraverser,
org.apache.hugegraph.traversal.algorithm.SameNeighborTraverser,
org.apache.hugegraph.traversal.algorithm.ShortestPathTraverser,
org.apache.hugegraph.traversal.algorithm.SingleSourceShortestPathTraverser,
org.apache.hugegraph.traversal.algorithm.SubGraphTraverser,
org.apache.hugegraph.traversal.algorithm.TemplatePathsTraverser,
org.apache.hugegraph.traversal.algorithm.steps.EdgeStep,
org.apache.hugegraph.traversal.algorithm.steps.RepeatEdgeStep,
org.apache.hugegraph.traversal.algorithm.steps.WeightedEdgeStep,
org.apache.hugegraph.traversal.optimize.ConditionP,
org.apache.hugegraph.traversal.optimize.Text,
org.apache.hugegraph.traversal.optimize.TraversalUtil,
org.opencypher.gremlin.traversal.CustomFunctions,
org.opencypher.gremlin.traversal.CustomPredicate
],
methodImports: [
java.lang.Math#*,
org.opencypher.gremlin.traversal.CustomPredicate#*,
org.opencypher.gremlin.traversal.CustomFunctions#*
]
},
org.apache.tinkerpop.gremlin.jsr223.ScriptFileGremlinPlugin: {
files: [scripts/empty-sample.groovy]
}
}
}
}
serializers:
- {className: org.apache.tinkerpop.gremlin.driver.ser.GraphBinaryMessageSerializerV1,
config: {
serializeResultToString: false,
ioRegistries: [org.apache.hugegraph.io.HugeGraphIoRegistry]
}
}
- {className: org.apache.tinkerpop.gremlin.driver.ser.GraphSONMessageSerializerV1d0,
config: {
serializeResultToString: false,
ioRegistries: [org.apache.hugegraph.io.HugeGraphIoRegistry]
}
}
- {className: org.apache.tinkerpop.gremlin.driver.ser.GraphSONMessageSerializerV2d0,
config: {
serializeResultToString: false,
ioRegistries: [org.apache.hugegraph.io.HugeGraphIoRegistry]
}
}
- {className: org.apache.tinkerpop.gremlin.driver.ser.GraphSONMessageSerializerV3d0,
config: {
serializeResultToString: false,
ioRegistries: [org.apache.hugegraph.io.HugeGraphIoRegistry]
}
}
metrics: {
consoleReporter: {enabled: false, interval: 180000},
csvReporter: {enabled: false, interval: 180000, fileName: ./metrics/gremlin-server-metrics.csv},
jmxReporter: {enabled: false},
slf4jReporter: {enabled: false, interval: 180000},
gangliaReporter: {enabled: false, interval: 180000, addressingMode: MULTICAST},
graphiteReporter: {enabled: false, interval: 180000}
}
maxInitialLineLength: 4096
maxHeaderSize: 8192
maxChunkSize: 8192
maxContentLength: 65536
maxAccumulationBufferComponents: 1024
resultIterationBatchSize: 64
writeBufferLowWaterMark: 32768
writeBufferHighWaterMark: 65536
ssl: {
enabled: false
}

View File

@ -1,144 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<!--
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.
-->
<!-- Config will be auto loaded every 60s -->
<configuration status="error" monitorInterval="60">
<properties>
<property name="LOG_PATH">logs</property>
<property name="FILE_NAME">hugegraph-server</property>
</properties>
<appenders>
<Console name="console" target="SYSTEM_OUT">
<ThresholdFilter level="DEBUG" onMatch="ACCEPT" onMismatch="DENY"/>
<PatternLayout pattern="%-d{yyyy-MM-dd HH:mm:ss} [%t] [%p] %c{1.} - %m%n"/>
</Console>
<!-- Normal server log config -->
<RollingRandomAccessFile name="file" fileName="${LOG_PATH}/${FILE_NAME}.log"
filePattern="${LOG_PATH}/$${date:yyyy-MM}/${FILE_NAME}-%d{yyyy-MM-dd}-%i.log"
immediateFlush="false">
<ThresholdFilter level="TRACE" onMatch="ACCEPT" onMismatch="DENY"/>
<PatternLayout pattern="%-d{yyyy-MM-dd HH:mm:ss} [%t] [%p] %c{1.} - %m%n"/>
<!-- Trigger after exceeding 1day or 50MB -->
<Policies>
<SizeBasedTriggeringPolicy size="50MB"/>
<TimeBasedTriggeringPolicy interval="1" modulate="true"/>
</Policies>
<!-- Keep 5 files per day & auto delete after over 2GB or 100 files -->
<DefaultRolloverStrategy max="5">
<Delete basePath="${LOG_PATH}" maxDepth="2">
<IfFileName glob="*/*.log"/>
<!-- Limit log amount & size -->
<IfAny>
<IfAccumulatedFileSize exceeds="2GB"/>
<IfAccumulatedFileCount exceeds="100"/>
</IfAny>
</Delete>
</DefaultRolloverStrategy>
</RollingRandomAccessFile>
<!-- Separate & compress audit log, buffer size is 512KB -->
<RollingRandomAccessFile name="audit" fileName="${LOG_PATH}/audit-${FILE_NAME}.log"
filePattern="${LOG_PATH}/$${date:yyyy-MM}/audit-${FILE_NAME}-%d{yyyy-MM-dd-HH}-%i.gz"
bufferSize="524288" immediateFlush="false">
<ThresholdFilter level="TRACE" onMatch="ACCEPT" onMismatch="DENY"/>
<!-- Use simple format for audit log to speed up -->
<PatternLayout pattern="%-d{yyyy-MM-dd HH:mm:ss} - %m%n"/>
<!-- Trigger after exceeding 1hour or 500MB -->
<Policies>
<SizeBasedTriggeringPolicy size="500MB"/>
<TimeBasedTriggeringPolicy interval="1" modulate="true"/>
</Policies>
<!-- Keep 2 files per hour & auto delete [after 60 days] or [over 5GB or 500 files] -->
<DefaultRolloverStrategy max="2">
<Delete basePath="${LOG_PATH}" maxDepth="2">
<IfFileName glob="*/*.gz"/>
<IfLastModified age="60d"/>
<IfAny>
<IfAccumulatedFileSize exceeds="5GB"/>
<IfAccumulatedFileCount exceeds="500"/>
</IfAny>
</Delete>
</DefaultRolloverStrategy>
</RollingRandomAccessFile>
<!-- Slow query log config -->
<RollingRandomAccessFile name="slowQueryLog" fileName="${LOG_PATH}/slow_query.log"
filePattern="${LOG_PATH}/$${date:yyyy-MM}/slow_query_log-%d{yyyy-MM-dd}-%i.log"
immediateFlush="false">
<ThresholdFilter level="TRACE" onMatch="ACCEPT" onMismatch="DENY"/>
<PatternLayout pattern="%-d{yyyy-MM-dd HH:mm:ss} [%t] [%p] %c{1.} - %m%n"/>
<!-- Trigger after exceeding 1day or 50MB -->
<Policies>
<SizeBasedTriggeringPolicy size="50MB"/>
<TimeBasedTriggeringPolicy interval="1" modulate="true"/>
</Policies>
<!-- Keep 5 files per day & auto delete after over 2GB or 100 files -->
<DefaultRolloverStrategy max="5">
<Delete basePath="${LOG_PATH}" maxDepth="2">
<IfFileName glob="*/*.log"/>
<!-- Limit log amount & size -->
<IfAny>
<IfAccumulatedFileSize exceeds="2GB"/>
<IfAccumulatedFileCount exceeds="100"/>
</IfAny>
</Delete>
</DefaultRolloverStrategy>
</RollingRandomAccessFile>
</appenders>
<loggers>
<root level="INFO">
<appender-ref ref="file"/>
</root>
<logger name="org.apache.cassandra" level="INFO" additivity="false">
<appender-ref ref="file"/>
</logger>
<logger name="org.apache.hadoop" level="INFO" additivity="false">
<appender-ref ref="file"/>
</logger>
<logger name="org.apache.zookeeper" level="WARN" additivity="false">
<appender-ref ref="file"/>
</logger>
<logger name="com.datastax.driver" level="WARN" additivity="false">
<appender-ref ref="file"/>
</logger>
<logger name="com.alipay.sofa" level="WARN" additivity="false">
<appender-ref ref="file"/>
</logger>
<logger name="io.netty" level="INFO" additivity="false">
<appender-ref ref="file"/>
</logger>
<logger name="org.apache.commons" level="INFO" additivity="false">
<appender-ref ref="file"/>
</logger>
<!-- Use mixed async way to output logs -->
<AsyncLogger name="org.apache.hugegraph" level="INFO" additivity="false">
<appender-ref ref="file"/>
</AsyncLogger>
<AsyncLogger name="org.apache.hugegraph.auth" level="INFO" additivity="false">
<appender-ref ref="audit"/>
</AsyncLogger>
<AsyncLogger name="org.apache.hugegraph.api.filter.AuthenticationFilter" level="INFO" additivity="false">
<appender-ref ref="audit"/>
</AsyncLogger>
<AsyncLogger name="org.apache.hugegraph.api.filter.AccessLogFilter" level="INFO" additivity="false">
<appender-ref ref="slowQueryLog"/>
</AsyncLogger>
</loggers>
</configuration>

View File

@ -1,30 +0,0 @@
#
# 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.
#
hosts: [localhost]
port: 8183
serializer: {
className: org.apache.tinkerpop.gremlin.driver.ser.GraphSONMessageSerializerV1d0,
config: {
serializeResultToString: false,
# The duplication of HugeGraphIoRegistry is meant to fix a bug in the
# 'org.apache.tinkerpop.gremlin.driver.Settings:from(Configuration)' method.
ioRegistries: [
org.apache.hugegraph.io.HugeGraphIoRegistry,
org.apache.hugegraph.io.HugeGraphIoRegistry
]
}
}

View File

@ -1,25 +0,0 @@
#
# 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.
#
hosts: [localhost]
port: 8183
serializer: {
className: org.apache.tinkerpop.gremlin.driver.ser.GraphSONMessageSerializerV1d0,
config: {
serializeResultToString: false,
ioRegistries: [org.apache.hugegraph.io.HugeGraphIoRegistry]
}
}

View File

@ -1,25 +0,0 @@
# bind url
restserver.url=http://127.0.0.1:8083
# gremlin server url, need to be consistent with host and port in gremlin-server.yaml
gremlinserver.url=http://127.0.0.1:8183
graphs=./conf/graphs
# configuration of arthas
arthas.telnet_port=8582
arthas.http_port=8581
arthas.ip=127.0.0.1
arthas.disabled_commands=jad
# authentication configs
# choose 'org.apache.hugegraph.auth.StandardAuthenticator' or
# 'org.apache.hugegraph.auth.ConfigAuthenticator'
#auth.authenticator=
# rpc server configs for multi graph-servers or raft-servers
rpc.server_host=127.0.0.1
rpc.server_port=8093
# lightweight load balancing (beta)
server.id=server-3
server.role=worker

View File

@ -1,180 +0,0 @@
#
# 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.
#
# TODO: reuse the configs for same type containers
# User could modify the node nums and the port by themselves
version: "3"
services:
pd0:
image: hugegraph/pd
container_name: pd0
hostname: pd0
network_mode: host
healthcheck:
test: ["CMD", "curl", "-f", "http://localhost:8620"]
interval: 10s
timeout: 5s
retries: 3
volumes:
- ./configs/application-pd0.yml:/hugegraph-pd/conf/application.yml
pd1:
image: hugegraph/pd
container_name: pd1
hostname: pd1
network_mode: host
healthcheck:
test: ["CMD", "curl", "-f", "http://localhost:8621"]
interval: 10s
timeout: 5s
retries: 3
volumes:
- ./configs/application-pd1.yml:/hugegraph-pd/conf/application.yml
pd2:
image: hugegraph/pd
container_name: pd2
hostname: pd2
network_mode: host
healthcheck:
test: ["CMD", "curl", "-f", "http://localhost:8622"]
interval: 10s
timeout: 5s
retries: 3
volumes:
- ./configs/application-pd2.yml:/hugegraph-pd/conf/application.yml
store0:
image: hugegraph/store
container_name: store0
hostname: store0
network_mode: host
depends_on:
pd0:
condition: service_healthy
pd1:
condition: service_healthy
pd2:
condition: service_healthy
healthcheck:
test: ["CMD", "curl", "-f", "http://localhost:8520"]
interval: 10s
timeout: 5s
retries: 3
volumes:
- ./configs/application-store0.yml:/hugegraph-store/conf/application.yml
store1:
image: hugegraph/store
container_name: store1
hostname: store1
network_mode: host
depends_on:
pd0:
condition: service_healthy
pd1:
condition: service_healthy
pd2:
condition: service_healthy
healthcheck:
test: ["CMD", "curl", "-f", "http://localhost:8521"]
interval: 10s
timeout: 5s
retries: 3
volumes:
- ./configs/application-store1.yml:/hugegraph-store/conf/application.yml
store2:
image: hugegraph/store
container_name: store2
hostname: store2
network_mode: host
depends_on:
pd0:
condition: service_healthy
pd1:
condition: service_healthy
pd2:
condition: service_healthy
healthcheck:
test: ["CMD", "curl", "-f", "http://localhost:8522"]
interval: 10s
timeout: 5s
retries: 3
volumes:
- ./configs/application-store2.yml:/hugegraph-store/conf/application.yml
server1:
image: hugegraph/server
container_name: server1
hostname: server1
network_mode: host
depends_on:
store0:
condition: service_healthy
store1:
condition: service_healthy
store2:
condition: service_healthy
healthcheck:
test: ["CMD", "curl", "-f", "http://localhost:8081"]
interval: 10s
timeout: 5s
retries: 3
volumes:
- ./configs/server1-conf:/hugegraph-server/conf
server2:
image: hugegraph/server
container_name: server2
hostname: server2
network_mode: host
depends_on:
store0:
condition: service_healthy
store1:
condition: service_healthy
store2:
condition: service_healthy
healthcheck:
test: ["CMD", "curl", "-f", "http://localhost:8082"]
interval: 10s
timeout: 5s
retries: 3
volumes:
- ./configs/server2-conf:/hugegraph-server/conf
server3:
image: hugegraph/server
container_name: server3
hostname: server3
network_mode: host
depends_on:
store0:
condition: service_healthy
store1:
condition: service_healthy
store2:
condition: service_healthy
healthcheck:
test: ["CMD", "curl", "-f", "http://localhost:8083"]
interval: 10s
timeout: 5s
retries: 3
volumes:
- ./configs/server3-conf:/hugegraph-server/conf

View File

@ -1,58 +0,0 @@
#
# 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.
#
version: "3"
services:
pd:
image: hugegraph/pd
container_name: pd
hostname: pd
network_mode: host
healthcheck:
test: ["CMD", "curl", "-f", "http://localhost:8620"]
interval: 10s
timeout: 5s
retries: 3
store:
image: hugegraph/store
container_name: store
hostname: store
network_mode: host
depends_on:
pd:
condition: service_healthy
healthcheck:
test: ["CMD", "curl", "-f", "http://localhost:8520"]
interval: 10s
timeout: 5s
retries: 3
server:
image: hugegraph/server
container_name: server
hostname: server
network_mode: host
depends_on:
store:
condition: service_healthy
healthcheck:
test: ["CMD", "curl", "-f", "http://localhost:8080"]
interval: 10s
timeout: 5s
retries: 3

112
hugegraph-api/pom.xml Normal file
View File

@ -0,0 +1,112 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<parent>
<artifactId>hugegraph</artifactId>
<groupId>com.baidu.hugegraph</groupId>
<version>0.7.4</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>hugegraph-api</artifactId>
<dependencies>
<dependency>
<groupId>com.baidu.hugegraph</groupId>
<artifactId>hugegraph-core</artifactId>
<version>${project.version}</version>
</dependency>
<dependency>
<groupId>org.apache.tinkerpop</groupId>
<artifactId>gremlin-server</artifactId>
<exclusions>
<exclusion>
<groupId>com.github.jeremyh</groupId>
<artifactId>jBCrypt</artifactId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>org.glassfish.jersey.core</groupId>
<artifactId>jersey-server</artifactId>
</dependency>
<dependency>
<groupId>org.glassfish.jersey.containers</groupId>
<artifactId>jersey-container-grizzly2-http</artifactId>
</dependency>
<dependency>
<groupId>org.glassfish.jersey.containers</groupId>
<artifactId>jersey-container-grizzly2-servlet</artifactId>
</dependency>
<dependency>
<groupId>org.glassfish.jersey.media</groupId>
<artifactId>jersey-media-json-jackson</artifactId>
</dependency>
<dependency>
<groupId>io.dropwizard.metrics</groupId>
<artifactId>metrics-jersey2</artifactId>
</dependency>
<dependency>
<groupId>io.dropwizard.metrics</groupId>
<artifactId>metrics-json</artifactId>
<exclusions>
<exclusion>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-core</artifactId>
</exclusion>
<exclusion>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-databind</artifactId>
</exclusion>
</exclusions>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<artifactId>maven-clean-plugin</artifactId>
<version>3.0.0</version>
<configuration>
<filesets>
<fileset>
<directory>${top.level.dir}</directory>
<includes>
<include>*.tar.gz</include>
</includes>
<followSymlinks>false</followSymlinks>
</fileset>
<fileset>
<directory>${final.name}</directory>
</fileset>
</filesets>
</configuration>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-jar-plugin</artifactId>
<version>3.0.2</version>
<configuration>
<archive>
<index>true</index>
<manifest>
<addDefaultImplementationEntries>
false
</addDefaultImplementationEntries>
<addDefaultSpecificationEntries>
true
</addDefaultSpecificationEntries>
</manifest>
<manifestEntries>
<Implementation-Version>0.27.0.0</Implementation-Version>
</manifestEntries>
</archive>
</configuration>
</plugin>
</plugins>
</build>
</project>

View File

@ -0,0 +1,183 @@
/*
* Copyright 2017 HugeGraph Authors
*
* 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.
*/
package com.baidu.hugegraph.api;
import java.util.Collection;
import java.util.Iterator;
import java.util.Map;
import java.util.concurrent.Callable;
import java.util.function.Consumer;
import javax.ws.rs.NotFoundException;
import javax.ws.rs.NotSupportedException;
import javax.ws.rs.core.MediaType;
import org.slf4j.Logger;
import com.baidu.hugegraph.HugeException;
import com.baidu.hugegraph.HugeGraph;
import com.baidu.hugegraph.api.schema.Checkable;
import com.baidu.hugegraph.core.GraphManager;
import com.baidu.hugegraph.metric.MetricsUtil;
import com.baidu.hugegraph.server.RestServer;
import com.baidu.hugegraph.type.HugeType;
import com.baidu.hugegraph.util.E;
import com.baidu.hugegraph.util.Log;
import com.codahale.metrics.Meter;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.google.common.collect.ImmutableMap;
public class API {
private static final Logger LOG = Log.logger(RestServer.class);
public static final String CHARSET = "UTF-8";
public static final String APPLICATION_JSON = MediaType.APPLICATION_JSON;
public static final String APPLICATION_JSON_WITH_CHARSET =
APPLICATION_JSON + ";charset=" + CHARSET;;
public static final String ACTION_APPEND = "append";
public static final String ACTION_ELIMINATE = "eliminate";
private static final Meter succeedMeter =
MetricsUtil.registerMeter(API.class, "commit-succeed");
private static final Meter illegalArgErrorMeter =
MetricsUtil.registerMeter(API.class, "illegal-arg");
private static final Meter expectedErrorMeter =
MetricsUtil.registerMeter(API.class, "expected-error");
private static final Meter unknownErrorMeter =
MetricsUtil.registerMeter(API.class, "unknown-error");
public static HugeGraph graph(GraphManager manager, String graph) {
HugeGraph g = manager.graph(graph);
if (g == null) {
throw new NotFoundException(String.format(
"Graph '%s' does not exist", graph));
}
return g;
}
public static <R> R commit(HugeGraph g, Callable<R> callable) {
Consumer<Throwable> rollback = (error) -> {
if (error != null) {
LOG.error("Failed to commit", error);
}
try {
g.tx().rollback();
} catch (Throwable e) {
LOG.error("Failed to rollback", e);
}
};
try {
R result = callable.call();
g.tx().commit();
succeedMeter.mark();
return result;
} catch (IllegalArgumentException | NotFoundException e) {
illegalArgErrorMeter.mark();
rollback.accept(null);
throw e;
} catch (RuntimeException e) {
expectedErrorMeter.mark();
rollback.accept(e);
throw e;
} catch (Throwable e) {
unknownErrorMeter.mark();
rollback.accept(e);
// TODO: throw the origin exception 'e'
throw new HugeException("Failed to commit", e);
}
}
public static void commit(HugeGraph g, Runnable runnable) {
commit(g, () -> {
runnable.run();
return null;
});
}
public static Object[] properties(Map<String, Object> properties) {
Object[] list = new Object[properties.size() * 2];
int i = 0;
for (Map.Entry<String, Object> prop : properties.entrySet()) {
list[i++] = prop.getKey();
list[i++] = prop.getValue();
}
return list;
}
protected static void checkExist(Iterator<?> iter,
HugeType type,
String id) {
if (!iter.hasNext()) {
throw new NotFoundException(String.format(
"%s with id '%s' does not exist", type, id));
}
}
protected static void checkCreatingBody(Checkable body) {
E.checkArgumentNotNull(body, "The request body can't be empty");
body.checkCreate(false);
}
protected static void checkUpdatingBody(Checkable body) {
E.checkArgumentNotNull(body, "The request body can't be empty");
body.checkUpdate();
}
protected static void checkCreatingBody(
Collection<? extends Checkable> bodys) {
E.checkArgumentNotNull(bodys, "The request body can't be empty");
for (Checkable body : bodys) {
E.checkArgumentNotNull(body,
"The batch body can't contain null record");
body.checkCreate(true);
}
}
@SuppressWarnings("unchecked")
protected static Map<String, Object> parseProperties(String properties) {
if (properties == null || properties.isEmpty()) {
return ImmutableMap.of();
}
ObjectMapper mapper = new ObjectMapper();
Map<String, Object> props = null;
try {
props = mapper.readValue(properties, Map.class);
} catch (Exception ignored) {}
// If properties is the string "null", props will be null
E.checkArgument(props != null, "Invalid request with none properties");
return props;
}
public static boolean checkAndParseAction(String action) {
E.checkArgumentNotNull(action, "The action param can't be empty");
if (action.equals(ACTION_APPEND)) {
return true;
} else if (action.equals(ACTION_ELIMINATE)) {
return false;
} else {
throw new NotSupportedException(
String.format("Not support action '%s'", action));
}
}
}

View File

@ -0,0 +1,189 @@
/*
* Copyright 2017 HugeGraph Authors
*
* 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.
*/
package com.baidu.hugegraph.api;
import java.io.File;
import java.util.Set;
import javax.annotation.security.RolesAllowed;
import javax.inject.Singleton;
import javax.ws.rs.Consumes;
import javax.ws.rs.DELETE;
import javax.ws.rs.GET;
import javax.ws.rs.NotSupportedException;
import javax.ws.rs.PUT;
import javax.ws.rs.Path;
import javax.ws.rs.PathParam;
import javax.ws.rs.Produces;
import javax.ws.rs.QueryParam;
import javax.ws.rs.core.Context;
import javax.ws.rs.core.SecurityContext;
import org.apache.tinkerpop.gremlin.structure.Edge;
import org.apache.tinkerpop.gremlin.structure.Vertex;
import org.slf4j.Logger;
import com.baidu.hugegraph.HugeGraph;
import com.baidu.hugegraph.core.GraphManager;
import com.baidu.hugegraph.schema.SchemaManager;
import com.baidu.hugegraph.server.RestServer;
import com.baidu.hugegraph.util.Log;
import com.codahale.metrics.annotation.Timed;
import com.fasterxml.jackson.annotation.JsonProperty;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableMap;
@Path("graphs")
@Singleton
public class GraphsAPI extends API {
private static final Logger LOG = Log.logger(RestServer.class);
private static final String CONFIRM_CLEAR = "I'm sure to delete all data";
@GET
@Timed
@Produces(APPLICATION_JSON_WITH_CHARSET)
@RolesAllowed({"admin", "$dynamic"})
public Object list(@Context GraphManager manager,
@Context SecurityContext sc) {
Set<String> graphs = manager.graphs().keySet();
String role = sc.getUserPrincipal().getName();
if (role.equals("admin")) {
return ImmutableMap.of("graphs", graphs);
} else {
// Filter by user role
String graph = role;
if (graphs.contains(graph)) {
return ImmutableMap.of("graphs", ImmutableList.of(graph));
} else {
return ImmutableMap.of("graphs", ImmutableList.of());
}
}
}
@GET
@Timed
@Path("{name}")
@Produces(APPLICATION_JSON_WITH_CHARSET)
@RolesAllowed({"admin", "$owner=name"})
public Object get(@Context GraphManager manager,
@PathParam("name") String name) {
LOG.debug("Get graph by name '{}'", name);
HugeGraph g = graph(manager, name);
return ImmutableMap.of("name", g.name(), "backend", g.backend());
}
@GET
@Timed
@Path("{name}/conf")
@Produces(APPLICATION_JSON_WITH_CHARSET)
@RolesAllowed("admin")
public File getConf(@Context GraphManager manager,
@PathParam("name") String name) {
LOG.debug("Get graph configuration by name '{}'", name);
HugeGraph g = graph(manager, name);
File file = g.configuration().getFile();
if (file == null) {
throw new NotSupportedException("Can't access the api in " +
"a node which started with non local file config.");
}
return file;
}
@DELETE
@Timed
@Path("{name}/clear")
@Consumes(APPLICATION_JSON)
@RolesAllowed("admin")
public void clear(@Context GraphManager manager,
@PathParam("name") String name,
@QueryParam("confirm_message") String message) {
LOG.debug("Clear graph by name '{}'", name);
HugeGraph g = graph(manager, name);
if (!CONFIRM_CLEAR.equals(message)) {
throw new IllegalArgumentException(String.format(
"Please take the message: %s", CONFIRM_CLEAR));
}
// Clear vertex and edge
commit(g, () -> {
g.traversal().E().toStream().forEach(Edge::remove);
g.traversal().V().toStream().forEach(Vertex::remove);
});
// Schema operation will auto commit
SchemaManager schema = g.schema();
schema.getIndexLabels().forEach(elem -> {
schema.indexLabel(elem.name()).remove();
});
schema.getEdgeLabels().forEach(elem -> {
schema.edgeLabel(elem.name()).remove();
});
schema.getVertexLabels().forEach(elem -> {
schema.vertexLabel(elem.name()).remove();
});
schema.getPropertyKeys().forEach(elem -> {
schema.propertyKey(elem.name()).remove();
});
}
@PUT
@Timed
@Path("{name}/restoring")
@Consumes(APPLICATION_JSON)
@Produces(APPLICATION_JSON_WITH_CHARSET)
@RolesAllowed("admin")
public Object restoring(@Context GraphManager manager,
@PathParam("name") String name,
JsonRestoring jsonRestoring) {
LOG.debug("Set restoring status to: '{}' of graph '{}'",
jsonRestoring, name);
HugeGraph g = graph(manager, name);
g.restoring(jsonRestoring.restoring);
return jsonRestoring;
}
@GET
@Timed
@Path("{name}/restoring")
@Consumes(APPLICATION_JSON)
@Produces(APPLICATION_JSON_WITH_CHARSET)
@RolesAllowed("admin")
public Object restoring(@Context GraphManager manager,
@PathParam("name") String name) {
LOG.debug("Get restoring status of graph '{}'", name);
HugeGraph g = graph(manager, name);
return ImmutableMap.of("restoring", g.restoring());
}
private static class JsonRestoring {
@JsonProperty("restoring")
public boolean restoring;
}
}

View File

@ -0,0 +1,114 @@
/*
* Copyright 2017 HugeGraph Authors
*
* 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.
*/
package com.baidu.hugegraph.api;
import javax.inject.Singleton;
import javax.ws.rs.Consumes;
import javax.ws.rs.GET;
import javax.ws.rs.POST;
import javax.ws.rs.Path;
import javax.ws.rs.Produces;
import javax.ws.rs.client.Client;
import javax.ws.rs.client.ClientBuilder;
import javax.ws.rs.client.Entity;
import javax.ws.rs.core.Context;
import javax.ws.rs.core.HttpHeaders;
import javax.ws.rs.core.MediaType;
import javax.ws.rs.core.Response;
import javax.ws.rs.core.UriInfo;
import com.baidu.hugegraph.api.filter.CompressInterceptor;
import com.baidu.hugegraph.api.filter.CompressInterceptor.Compress;
import com.baidu.hugegraph.config.HugeConfig;
import com.baidu.hugegraph.config.ServerOptions;
import com.codahale.metrics.annotation.Timed;
@Path("gremlin")
@Singleton
public class GremlinAPI extends API {
private Client client = ClientBuilder.newClient();
private Response doGetRequest(String location, String auth, String query) {
String url = String.format("%s?%s", location, query);
Response r = this.client.target(url)
.request()
.header(HttpHeaders.AUTHORIZATION, auth)
.accept(MediaType.APPLICATION_JSON)
.acceptEncoding(CompressInterceptor.GZIP)
.get();
if (r.getMediaType() != null) {
// Append charset
assert MediaType.APPLICATION_JSON_TYPE.equals(r.getMediaType());
r.getHeaders().putSingle(HttpHeaders.CONTENT_TYPE,
r.getMediaType().withCharset(CHARSET));
}
return r;
}
private Response doPostRequest(String location, String auth, Object req) {
Entity<?> body = Entity.entity(req, MediaType.APPLICATION_JSON);
Response r = this.client.target(location)
.request()
.header(HttpHeaders.AUTHORIZATION, auth)
.accept(MediaType.APPLICATION_JSON)
.acceptEncoding(CompressInterceptor.GZIP)
.post(body);
if (r.getMediaType() != null) {
// Append charset
assert MediaType.APPLICATION_JSON_TYPE.equals(r.getMediaType());
r.getHeaders().putSingle(HttpHeaders.CONTENT_TYPE,
r.getMediaType().withCharset(CHARSET));
}
return r;
}
@POST
@Timed
@Compress
@Consumes(APPLICATION_JSON)
@Produces(APPLICATION_JSON_WITH_CHARSET)
public Response post(@Context HugeConfig conf,
@Context HttpHeaders headers,
String request) {
/* The following code is reserved for forwarding request */
// context.getRequestDispatcher(location).forward(request, response);
// return Response.seeOther(UriBuilder.fromUri(location).build())
// .build();
// Response.temporaryRedirect(UriBuilder.fromUri(location).build())
// .build();
String location = conf.get(ServerOptions.GREMLIN_SERVER_URL);
String auth = headers.getHeaderString(HttpHeaders.AUTHORIZATION);
return doPostRequest(location, auth, request);
}
@GET
@Timed
@Compress(buffer=(1024 * 40))
@Produces(APPLICATION_JSON_WITH_CHARSET)
public Response get(@Context HugeConfig conf,
@Context HttpHeaders headers,
@Context UriInfo uriInfo) {
String location = conf.get(ServerOptions.GREMLIN_SERVER_URL);
String auth = headers.getHeaderString(HttpHeaders.AUTHORIZATION);
String query = uriInfo.getRequestUri().getRawQuery();
return doGetRequest(location, auth, query);
}
}

View File

@ -0,0 +1,50 @@
/*
* Copyright 2017 HugeGraph Authors
*
* 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.
*/
package com.baidu.hugegraph.api;
import java.util.Map;
import javax.annotation.security.PermitAll;
import javax.inject.Singleton;
import javax.ws.rs.GET;
import javax.ws.rs.Path;
import javax.ws.rs.Produces;
import com.baidu.hugegraph.version.ApiVersion;
import com.baidu.hugegraph.version.CoreVersion;
import com.codahale.metrics.annotation.Timed;
import com.google.common.collect.ImmutableMap;
@Path("versions")
@Singleton
public class VersionAPI extends API {
@GET
@Timed
@Produces(APPLICATION_JSON_WITH_CHARSET)
@PermitAll
public Object list() {
Map<String, String> versions = ImmutableMap.of("version", "v1",
"core", CoreVersion.VERSION.toString(),
"gremlin", CoreVersion.GREMLIN_VERSION,
"api", ApiVersion.VERSION.toString());
return ImmutableMap.of("versions", versions);
}
}

View File

@ -0,0 +1,219 @@
/*
* Copyright 2017 HugeGraph Authors
*
* 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.
*/
package com.baidu.hugegraph.api.filter;
import java.io.IOException;
import java.security.Principal;
import java.util.List;
import javax.annotation.Priority;
import javax.ws.rs.BadRequestException;
import javax.ws.rs.NotAuthorizedException;
import javax.ws.rs.Priorities;
import javax.ws.rs.container.ContainerRequestContext;
import javax.ws.rs.container.ContainerRequestFilter;
import javax.ws.rs.container.PreMatching;
import javax.ws.rs.core.Context;
import javax.ws.rs.core.HttpHeaders;
import javax.ws.rs.core.SecurityContext;
import javax.ws.rs.core.UriInfo;
import javax.ws.rs.ext.Provider;
import javax.xml.bind.DatatypeConverter;
import org.glassfish.grizzly.utils.Charsets;
import com.baidu.hugegraph.auth.StandardAuthenticator;
import com.baidu.hugegraph.core.GraphManager;
import com.baidu.hugegraph.util.E;
@Provider
@PreMatching
@Priority(Priorities.AUTHENTICATION)
public class AuthenticationFilter implements ContainerRequestFilter {
@Context
private javax.inject.Provider<GraphManager> managerProvider;
@Override
public void filter(ContainerRequestContext context) throws IOException {
User user = this.authenticate(context);
Authorizer authorizer = new Authorizer(user, context.getUriInfo());
context.setSecurityContext(authorizer);
}
protected User authenticate(ContainerRequestContext context) {
GraphManager manager = this.managerProvider.get();
E.checkState(manager != null, "Context GraphManager is absent");
if (!manager.requireAuthentication()) {
// Return anonymous user with admin role if disable authentication
final String username = StandardAuthenticator.USER_ANONYMOUS;
final String role = StandardAuthenticator.ROLE_ADMIN;
return new User(username, role);
}
// Extract authentication credentials
String auth = context.getHeaderString(HttpHeaders.AUTHORIZATION);
if (auth == null) {
throw new NotAuthorizedException(
"Authentication credentials are required");
}
if (!auth.startsWith("Basic ")) {
throw new BadRequestException(
"Only HTTP Basic authentication is supported");
}
auth = auth.substring("Basic ".length());
auth = new String(DatatypeConverter.parseBase64Binary(auth),
Charsets.ASCII_CHARSET);
String[] values = auth.split(":");
if (values.length != 2) {
throw new BadRequestException(
"Invalid syntax for username and password");
}
final String username = values[0];
final String password = values[1];
assert username != null && password != null;
// Validate the extracted credentials
final String role = manager.authenticate(username, password);
if (!StandardAuthenticator.verifyRole(role)) {
throw new NotAuthorizedException("Invalid username or password");
}
return new User(username, role);
}
public static class Authorizer implements SecurityContext {
private final UriInfo uri;
private final User user;
private final Principal principal;
public Authorizer(final User user, final UriInfo uri) {
E.checkNotNull(user, "user");
E.checkNotNull(uri, "uri");
this.uri = uri;
this.user = user;
this.principal = new UserPrincipal();
}
public String username() {
return this.user.username;
}
public String userrole() {
return this.user.role;
}
@Override
public Principal getUserPrincipal() {
return this.principal;
}
@Override
public boolean isUserInRole(String role) {
if (role.equals(StandardAuthenticator.ROLE_DYNAMIC)) {
// Let the resource itself dynamically determine
return true;
} else if (role.startsWith(StandardAuthenticator.ROLE_OWNER)) {
// Role format like: "$owner=name"
String[] owner = role.split("=", 2);
E.checkState(owner.length == 2, "Bad role format: '%s'", role);
role = this.getPathParameter(owner[1]);
}
return role.equals(this.user.role);
}
@Override
public boolean isSecure() {
return "https".equals(this.uri.getRequestUri().getScheme());
}
@Override
public String getAuthenticationScheme() {
return SecurityContext.BASIC_AUTH;
}
private String getPathParameter(String key) {
List<String> params = this.uri.getPathParameters().get(key);
E.checkState(params != null && params.size() == 1,
"There is no matched path parameter: '%s'", key);
return params.get(0);
}
private final class UserPrincipal implements Principal {
@Override
public String getName() {
return Authorizer.this.user.role;
}
@Override
public String toString() {
return Authorizer.this.user.toString();
}
@Override
public int hashCode() {
return Authorizer.this.user.hashCode();
}
@Override
public boolean equals(Object obj) {
return Authorizer.this.user.equals(obj);
}
}
}
protected static class User {
private String username;
private String role;
public User(String username, String role) {
this.username = username;
this.role = role;
}
@Override
public int hashCode() {
return this.username.hashCode() ^ this.role.hashCode();
}
@Override
public boolean equals(Object obj) {
if (obj == null || !(obj instanceof User)) {
return false;
}
User other = (User) obj;
return this.username.equals(other.username) &&
this.role.equals(other.role);
}
@Override
public String toString() {
return String.format("User{username=%s,role=%s}",
this.username, this.role);
}
}
}

View File

@ -1,21 +1,23 @@
/*
* Copyright 2017 HugeGraph Authors
*
* 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
* 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.
* 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.hugegraph.api.filter;
package com.baidu.hugegraph.api.filter;
import java.io.IOException;
import java.io.OutputStream;
@ -24,33 +26,34 @@ import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.util.zip.GZIPOutputStream;
import org.apache.hugegraph.api.filter.CompressInterceptor.Compress;
import org.apache.hugegraph.util.Log;
import javax.inject.Singleton;
import javax.ws.rs.NameBinding;
import javax.ws.rs.WebApplicationException;
import javax.ws.rs.core.MultivaluedMap;
import javax.ws.rs.ext.Provider;
import javax.ws.rs.ext.WriterInterceptor;
import javax.ws.rs.ext.WriterInterceptorContext;
import org.slf4j.Logger;
import jakarta.inject.Singleton;
import jakarta.ws.rs.NameBinding;
import jakarta.ws.rs.WebApplicationException;
import jakarta.ws.rs.core.MultivaluedMap;
import jakarta.ws.rs.ext.Provider;
import jakarta.ws.rs.ext.WriterInterceptor;
import jakarta.ws.rs.ext.WriterInterceptorContext;
import com.baidu.hugegraph.server.RestServer;
import com.baidu.hugegraph.util.Log;
@Provider
@Singleton
@Compress
@CompressInterceptor.Compress
public class CompressInterceptor implements WriterInterceptor {
public static final String GZIP = "gzip";
private static final Logger LOG = Log.logger(CompressInterceptor.class);
private static final Logger LOG = Log.logger(RestServer.class);
// Set compress output buffer size to 4KB (about 40~600 vertices)
public static final int BUFFER_SIZE = 1024 * 4;
@Override
public void aroundWriteTo(WriterInterceptorContext context)
throws IOException, WebApplicationException {
throws IOException, WebApplicationException {
// If there is no annotation(like exception), we don't compress it
if (context.getAnnotations().length > 0) {
try {
@ -69,14 +72,14 @@ public class CompressInterceptor implements WriterInterceptor {
}
private void compress(WriterInterceptorContext context)
throws IOException {
throws IOException {
// Get compress info from the @Compress annotation
final Compress compression = getCompressAnnotation(context);
final String encoding = compression.value();
final int buffer = compression.buffer();
// Update header
MultivaluedMap<String, Object> headers = context.getHeaders();
MultivaluedMap<String,Object> headers = context.getHeaders();
headers.remove("Content-Length");
headers.add("Content-Encoding", encoding);
@ -103,9 +106,7 @@ public class CompressInterceptor implements WriterInterceptor {
@NameBinding
@Retention(RetentionPolicy.RUNTIME)
public @interface Compress {
String value() default GZIP;
int buffer() default BUFFER_SIZE;
}
}

View File

@ -1,32 +1,34 @@
/*
* Copyright 2017 HugeGraph Authors
*
* 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
* 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.
* 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.hugegraph.api.filter;
package com.baidu.hugegraph.api.filter;
import java.io.IOException;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.util.zip.GZIPInputStream;
import jakarta.inject.Singleton;
import jakarta.ws.rs.NameBinding;
import jakarta.ws.rs.ext.Provider;
import jakarta.ws.rs.ext.ReaderInterceptor;
import jakarta.ws.rs.ext.ReaderInterceptorContext;
import javax.inject.Singleton;
import javax.ws.rs.NameBinding;
import javax.ws.rs.ext.Provider;
import javax.ws.rs.ext.ReaderInterceptor;
import javax.ws.rs.ext.ReaderInterceptorContext;
@Provider
@Singleton
@ -37,7 +39,7 @@ public class DecompressInterceptor implements ReaderInterceptor {
@Override
public Object aroundReadFrom(ReaderInterceptorContext context)
throws IOException {
throws IOException {
// NOTE: Currently we just support GZIP
String encoding = context.getHeaders().getFirst("Content-Encoding");
if (!GZIP.equalsIgnoreCase(encoding)) {
@ -47,10 +49,10 @@ public class DecompressInterceptor implements ReaderInterceptor {
return context.proceed();
}
@NameBinding
@Retention(RetentionPolicy.RUNTIME)
public @interface Decompress {
String value() default GZIP;
}
}

View File

@ -0,0 +1,173 @@
/*
* Copyright 2017 HugeGraph Authors
*
* 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.
*/
package com.baidu.hugegraph.api.filter;
import java.util.NoSuchElementException;
import javax.json.Json;
import javax.json.JsonArrayBuilder;
import javax.json.JsonObjectBuilder;
import javax.ws.rs.WebApplicationException;
import javax.ws.rs.core.Context;
import javax.ws.rs.core.MediaType;
import javax.ws.rs.core.Response;
import javax.ws.rs.ext.ExceptionMapper;
import javax.ws.rs.ext.Provider;
import com.baidu.hugegraph.HugeException;
import com.baidu.hugegraph.config.HugeConfig;
import com.baidu.hugegraph.config.ServerOptions;
import com.baidu.hugegraph.exception.NotFoundException;
public class ExceptionFilter {
public static class TracedExceptionMapper {
@Context
private javax.inject.Provider<HugeConfig> configProvider;
protected boolean trace() {
HugeConfig config = this.configProvider.get();
if (config == null) {
return false;
}
return config.get(ServerOptions.ALLOW_TRACE);
}
}
@Provider
public static class HugeExceptionMapper
implements ExceptionMapper<HugeException> {
@Override
public Response toResponse(HugeException exception) {
return Response.status(400)
.type(MediaType.APPLICATION_JSON)
.entity(formatException(exception))
.build();
}
}
@Provider
public static class IllegalArgumentExceptionMapper
implements ExceptionMapper<IllegalArgumentException> {
@Override
public Response toResponse(IllegalArgumentException exception) {
return Response.status(400)
.type(MediaType.APPLICATION_JSON)
.entity(formatException(exception))
.build();
}
}
@Provider
public static class NotFoundExceptionMapper
implements ExceptionMapper<NotFoundException> {
@Override
public Response toResponse(NotFoundException exception) {
return Response.status(404)
.type(MediaType.APPLICATION_JSON)
.entity(formatException(exception))
.build();
}
}
@Provider
public static class NoSuchElementExceptionMapper
implements ExceptionMapper<NoSuchElementException> {
@Override
public Response toResponse(NoSuchElementException exception) {
return Response.status(404)
.type(MediaType.APPLICATION_JSON)
.entity(formatException(exception))
.build();
}
}
@Provider
public static class WebApplicationExceptionMapper
extends TracedExceptionMapper
implements ExceptionMapper<WebApplicationException> {
private static final int INTERNAL_SERVER_ERROR =
Response.Status.INTERNAL_SERVER_ERROR.getStatusCode();
@Override
public Response toResponse(WebApplicationException exception) {
Response response = exception.getResponse();
if (response.hasEntity()) {
return response;
}
boolean trace = this.trace(response.getStatus());
return Response.status(response.getStatus())
.type(MediaType.APPLICATION_JSON)
.entity(formatException(exception, trace))
.build();
}
private boolean trace(int status) {
return this.trace() && status == INTERNAL_SERVER_ERROR;
}
}
@Provider
public static class UnknownExceptionMapper extends TracedExceptionMapper
implements ExceptionMapper<Exception> {
@Override
public Response toResponse(Exception exception) {
return Response.status(500)
.type(MediaType.APPLICATION_JSON)
.entity(formatException(exception, this.trace()))
.build();
}
}
public static String formatException(Exception exception) {
return formatException(exception, false);
}
public static String formatException(Exception exception, boolean trace) {
String msg = exception.getMessage() != null ?
exception.getMessage() : "";
String cause = exception.getCause() != null ?
exception.getCause().toString() : "";
JsonObjectBuilder json = Json.createObjectBuilder()
.add("exception", exception.getClass().toString())
.add("message", msg)
.add("cause", cause);
if (trace) {
JsonArrayBuilder traces = Json.createArrayBuilder();
for (StackTraceElement i : exception.getStackTrace()) {
traces.add(i.toString());
}
json.add("trace", traces);
}
return json.build().toString();
}
}

View File

@ -1,32 +1,34 @@
/*
* Copyright 2017 HugeGraph Authors
*
* 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
* 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.
* 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.hugegraph.api.filter;
package com.baidu.hugegraph.api.filter;
import java.io.IOException;
import java.lang.annotation.Annotation;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import jakarta.ws.rs.NameBinding;
import jakarta.ws.rs.container.ContainerRequestContext;
import jakarta.ws.rs.container.ContainerResponseContext;
import jakarta.ws.rs.container.ContainerResponseFilter;
import jakarta.ws.rs.ext.Provider;
import javax.ws.rs.NameBinding;
import javax.ws.rs.container.ContainerRequestContext;
import javax.ws.rs.container.ContainerResponseContext;
import javax.ws.rs.container.ContainerResponseFilter;
import javax.ws.rs.ext.Provider;
@Provider
public class StatusFilter implements ContainerResponseFilter {
@ -34,7 +36,7 @@ public class StatusFilter implements ContainerResponseFilter {
@Override
public void filter(ContainerRequestContext requestContext,
ContainerResponseContext responseContext)
throws IOException {
throws IOException {
if (responseContext.getStatus() == 200) {
for (Annotation i : responseContext.getEntityAnnotations()) {
if (i instanceof Status) {
@ -48,7 +50,6 @@ public class StatusFilter implements ContainerResponseFilter {
@NameBinding
@Retention(RetentionPolicy.RUNTIME)
public @interface Status {
int OK = 200;
int CREATED = 201;
int ACCEPTED = 202;

View File

@ -0,0 +1,74 @@
/*
* Copyright 2017 HugeGraph Authors
*
* 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.
*/
package com.baidu.hugegraph.api.graph;
import java.util.concurrent.Callable;
import java.util.concurrent.atomic.AtomicInteger;
import org.slf4j.Logger;
import com.baidu.hugegraph.HugeException;
import com.baidu.hugegraph.HugeGraph;
import com.baidu.hugegraph.api.API;
import com.baidu.hugegraph.config.HugeConfig;
import com.baidu.hugegraph.config.ServerOptions;
import com.baidu.hugegraph.metric.MetricsUtil;
import com.baidu.hugegraph.server.RestServer;
import com.baidu.hugegraph.util.Log;
import com.codahale.metrics.Meter;
public class BatchAPI extends API {
private static final Logger LOG = Log.logger(RestServer.class);
// NOTE: VertexAPI and EdgeAPI should share a counter
private static final AtomicInteger batchWriteThreads = new AtomicInteger(0);
static {
MetricsUtil.registerGauge(RestServer.class, "batch-write-threads",
() -> batchWriteThreads.intValue());
}
private final Meter batchMeter;
public BatchAPI() {
this.batchMeter = MetricsUtil.registerMeter(this.getClass(),
"batch-insert");
}
public <R> R commit(HugeConfig config, HugeGraph g, int size,
Callable<R> callable) {
int maxWriteThreads = config.get(ServerOptions.MAX_WRITE_THREADS);
int writingThreads = batchWriteThreads.incrementAndGet();
if (writingThreads > maxWriteThreads) {
batchWriteThreads.decrementAndGet();
throw new HugeException("The rest server is too busy to write");
}
LOG.debug("The batch writing threads is {}", batchWriteThreads);
try {
R result = commit(g, callable);
this.batchMeter.mark(size);
return result;
} finally {
batchWriteThreads.decrementAndGet();
}
}
}

View File

@ -0,0 +1,419 @@
/*
* Copyright 2017 HugeGraph Authors
*
* 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.
*/
package com.baidu.hugegraph.api.graph;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.NoSuchElementException;
import javax.inject.Singleton;
import javax.ws.rs.Consumes;
import javax.ws.rs.DELETE;
import javax.ws.rs.DefaultValue;
import javax.ws.rs.GET;
import javax.ws.rs.POST;
import javax.ws.rs.PUT;
import javax.ws.rs.Path;
import javax.ws.rs.PathParam;
import javax.ws.rs.Produces;
import javax.ws.rs.QueryParam;
import javax.ws.rs.core.Context;
import org.apache.tinkerpop.gremlin.process.traversal.dsl.graph.GraphTraversal;
import org.apache.tinkerpop.gremlin.structure.Direction;
import org.apache.tinkerpop.gremlin.structure.Edge;
import org.apache.tinkerpop.gremlin.structure.Vertex;
import org.apache.tinkerpop.gremlin.util.function.TriFunction;
import org.slf4j.Logger;
import com.baidu.hugegraph.HugeGraph;
import com.baidu.hugegraph.api.API;
import com.baidu.hugegraph.api.filter.CompressInterceptor.Compress;
import com.baidu.hugegraph.api.filter.DecompressInterceptor.Decompress;
import com.baidu.hugegraph.api.filter.StatusFilter.Status;
import com.baidu.hugegraph.api.schema.Checkable;
import com.baidu.hugegraph.backend.id.Id;
import com.baidu.hugegraph.backend.tx.SchemaTransaction;
import com.baidu.hugegraph.config.HugeConfig;
import com.baidu.hugegraph.config.ServerOptions;
import com.baidu.hugegraph.core.GraphManager;
import com.baidu.hugegraph.exception.NotFoundException;
import com.baidu.hugegraph.schema.EdgeLabel;
import com.baidu.hugegraph.schema.PropertyKey;
import com.baidu.hugegraph.schema.VertexLabel;
import com.baidu.hugegraph.server.RestServer;
import com.baidu.hugegraph.structure.HugeEdge;
import com.baidu.hugegraph.structure.HugeVertex;
import com.baidu.hugegraph.type.HugeType;
import com.baidu.hugegraph.util.E;
import com.baidu.hugegraph.util.Log;
import com.codahale.metrics.annotation.Timed;
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
import com.fasterxml.jackson.annotation.JsonProperty;
@Path("graphs/{graph}/graph/edges")
@Singleton
public class EdgeAPI extends BatchAPI {
private static final Logger LOG = Log.logger(RestServer.class);
@POST
@Timed
@Status(Status.CREATED)
@Consumes(APPLICATION_JSON)
@Produces(APPLICATION_JSON_WITH_CHARSET)
public String create(@Context GraphManager manager,
@PathParam("graph") String graph,
JsonEdge jsonEdge) {
LOG.debug("Graph [{}] create edge: {}", graph, jsonEdge);
checkCreatingBody(jsonEdge);
HugeGraph g = graph(manager, graph);
if (jsonEdge.sourceLabel != null && jsonEdge.targetLabel != null) {
// NOTE: Not use SchemaManager because it will throw 404
SchemaTransaction schema = g.schemaTransaction();
/*
* NOTE: If the vertex id is correct but label not match with id,
* we allow to create it here
*/
E.checkArgumentNotNull(schema.getVertexLabel(jsonEdge.sourceLabel),
"Invalid source vertex label '%s'",
jsonEdge.sourceLabel);
E.checkArgumentNotNull(schema.getVertexLabel(jsonEdge.targetLabel),
"Invalid target vertex label '%s'",
jsonEdge.targetLabel);
}
Vertex srcVertex = getVertex(g, jsonEdge.source, null);
Vertex tgtVertex = getVertex(g, jsonEdge.target, null);
Edge edge = commit(g, () -> {
return srcVertex.addEdge(jsonEdge.label, tgtVertex,
jsonEdge.properties());
});
return manager.serializer(g).writeEdge(edge);
}
@POST
@Timed
@Decompress
@Path("batch")
@Status(Status.CREATED)
@Consumes(APPLICATION_JSON)
@Produces(APPLICATION_JSON_WITH_CHARSET)
public List<String> create(@Context HugeConfig config,
@Context GraphManager manager,
@PathParam("graph") String graph,
@QueryParam("check_vertex")
@DefaultValue("true") boolean checkVertex,
List<JsonEdge> jsonEdges) {
LOG.debug("Graph [{}] create edges: {}", graph, jsonEdges);
checkCreatingBody(jsonEdges);
HugeGraph g = graph(manager, graph);
checkBatchSize(g, jsonEdges);
TriFunction<HugeGraph, Object, String, Vertex> getVertex =
checkVertex ? EdgeAPI::getVertex : EdgeAPI::newVertex;
return this.commit(config, g, jsonEdges.size(), () -> {
List<String> ids = new ArrayList<>(jsonEdges.size());
for (JsonEdge jsonEdge : jsonEdges) {
/*
* NOTE: If the query param 'checkVertex' is false,
* then the label is correct and not matched id,
* it will be allowed currently
*/
Vertex srcVertex = getVertex.apply(g, jsonEdge.source,
jsonEdge.sourceLabel);
Vertex tgtVertex = getVertex.apply(g, jsonEdge.target,
jsonEdge.targetLabel);
Edge edge = srcVertex.addEdge(jsonEdge.label, tgtVertex,
jsonEdge.properties());
ids.add(edge.id().toString());
}
return ids;
});
}
@PUT
@Timed
@Path("{id}")
@Consumes(APPLICATION_JSON)
@Produces(APPLICATION_JSON_WITH_CHARSET)
public String update(@Context GraphManager manager,
@PathParam("graph") String graph,
@PathParam("id") String id,
@QueryParam("action") String action,
JsonEdge jsonEdge) {
LOG.debug("Graph [{}] update edge: {}", graph, jsonEdge);
checkUpdatingBody(jsonEdge);
if (jsonEdge.id != null) {
E.checkArgument(id.equals(jsonEdge.id),
"The ids are different between url('%s') and " +
"request body('%s')", id, jsonEdge.id);
}
// Parse action param
boolean append = checkAndParseAction(action);
HugeGraph g = graph(manager, graph);
HugeEdge edge = (HugeEdge) g.edges(id).next();
EdgeLabel edgeLabel = edge.schemaLabel();
for (String key : jsonEdge.properties.keySet()) {
PropertyKey pkey = g.propertyKey(key);
E.checkArgument(edgeLabel.properties().contains(pkey.id()),
"Can't update property for edge '%s' because " +
"there is no property key '%s' in its edge label",
id, key);
}
commit(g, () -> {
for (Map.Entry<String, Object> e : jsonEdge.properties.entrySet()) {
String key = e.getKey();
Object value = e.getValue();
if (append) {
edge.property(key, value);
} else {
edge.property(key).remove();
}
}
});
return manager.serializer(g).writeEdge(edge);
}
@GET
@Timed
@Compress
@Produces(APPLICATION_JSON_WITH_CHARSET)
public String list(@Context GraphManager manager,
@PathParam("graph") String graph,
@QueryParam("vertex_id") String vertexId,
@QueryParam("direction") String direction,
@QueryParam("label") String label,
@QueryParam("properties") String properties,
@QueryParam("offset") @DefaultValue("0") long offset,
@QueryParam("page") String page,
@QueryParam("limit") @DefaultValue("100") long limit) {
LOG.debug("Graph [{}] query edges by vertex: {}, direction: {}, " +
"label: {}, properties: {}, offset: {}, page: {}, limit: {}",
vertexId, direction, label, properties, offset, page, limit);
if (page != null) {
E.checkArgument(vertexId == null && direction == null &&
label == null && properties == null && offset == 0,
"Not support quering edges based on paging and " +
"[vertex, direction, label, properties, offset] " +
"together");
}
Id vertex = VertexAPI.checkAndParseVertexId(vertexId);
Direction dir = parseDirection(direction);
Map<String, Object> props = parseProperties(properties);
HugeGraph g = graph(manager, graph);
GraphTraversal<?, Edge> traversal;
if (vertex != null) {
if (label != null) {
traversal = g.traversal().V(vertex).toE(dir, label);
} else {
traversal = g.traversal().V(vertex).toE(dir);
}
} else {
if (label != null) {
traversal = g.traversal().E().hasLabel(label);
} else {
traversal = g.traversal().E();
}
}
for (Map.Entry<String, Object> entry : props.entrySet()) {
traversal = traversal.has(entry.getKey(), entry.getValue());
}
if (page == null) {
traversal = traversal.range(offset, offset + limit);
} else {
traversal = traversal.has("~page", page).limit(limit);
}
return manager.serializer(g).writeEdges(traversal, page != null);
}
@GET
@Timed
@Path("{id}")
@Produces(APPLICATION_JSON_WITH_CHARSET)
public String get(@Context GraphManager manager,
@PathParam("graph") String graph,
@PathParam("id") String id) {
LOG.debug("Graph [{}] get edge by id '{}'", graph, id);
HugeGraph g = graph(manager, graph);
Iterator<Edge> edges = g.edges(id);
checkExist(edges, HugeType.EDGE, id);
return manager.serializer(g).writeEdge(edges.next());
}
@DELETE
@Timed
@Path("{id}")
@Consumes(APPLICATION_JSON)
public void delete(@Context GraphManager manager,
@PathParam("graph") String graph,
@PathParam("id") String id) {
LOG.debug("Graph [{}] remove vertex by id '{}'", graph, id);
HugeGraph g = graph(manager, graph);
// TODO: add removeEdge(id) to improve
commit(g, () -> {
Edge edge;
try {
edge = g.edges(id).next();
} catch (NotFoundException e) {
throw new IllegalArgumentException(e.getMessage());
} catch (NoSuchElementException e) {
throw new IllegalArgumentException(String.format(
"No such edge with id: '%s'", id));
}
edge.remove();
});
}
private static void checkBatchSize(HugeGraph g, List<JsonEdge> edges) {
int max = g.configuration().get(ServerOptions.MAX_EDGES_PER_BATCH);
if (edges.size() > max) {
throw new IllegalArgumentException(String.format(
"Too many counts of edges for one time post, " +
"the maximum number is '%s'", max));
}
}
private static Vertex getVertex(HugeGraph graph, Object id, String label) {
HugeVertex vertex;
try {
vertex = (HugeVertex) graph.vertices(id).next();
} catch (NoSuchElementException e) {
throw new IllegalArgumentException(String.format(
"Invalid vertex id '%s'", id));
}
// Clone a new vertex to support multi-thread access
return vertex.copy().resetTx();
}
private static Vertex newVertex(HugeGraph graph, Object id, String label) {
// NOTE: Not use SchemaManager because it will throw 404
VertexLabel vl = graph.schemaTransaction().getVertexLabel(label);
E.checkArgumentNotNull(vl, "Invalid vertex label '%s'", label);
Id idValue = HugeVertex.getIdValue(id);
return new HugeVertex(graph, idValue, vl);
}
public static Direction parseDirection(String direction) {
if (direction == null || direction.isEmpty()) {
return Direction.BOTH;
}
try {
return Direction.valueOf(direction);
} catch (Exception e) {
throw new IllegalArgumentException(String.format(
"Direction value must be in [OUT, IN, BOTH], " +
"but got '%s'", direction));
}
}
@JsonIgnoreProperties(value = {"type"})
private static class JsonEdge implements Checkable {
@JsonProperty("id")
public String id;
@JsonProperty("outV")
public Object source;
@JsonProperty("outVLabel")
public String sourceLabel;
@JsonProperty("label")
public String label;
@JsonProperty("inV")
public Object target;
@JsonProperty("inVLabel")
public String targetLabel;
@JsonProperty("properties")
public Map<String, Object> properties;
@JsonProperty("type")
public String type;
@Override
public void checkCreate(boolean isBatch) {
E.checkArgumentNotNull(this.label, "Expect the label of edge");
E.checkArgumentNotNull(this.source, "Expect source vertex id");
E.checkArgumentNotNull(this.target, "Expect target vertex id");
if (isBatch) {
E.checkArgumentNotNull(this.sourceLabel,
"Expect source vertex label");
E.checkArgumentNotNull(this.targetLabel,
"Expect target vertex label");
} else {
E.checkArgument(this.sourceLabel == null &&
this.targetLabel == null ||
this.sourceLabel != null &&
this.targetLabel != null,
"The both source and target vertex label " +
"are either passed in, or not passed in");
}
this.checkUpdate();
}
@Override
public void checkUpdate() {
E.checkArgumentNotNull(this.properties,
"The properties of edge can't be null");
for (Map.Entry<String, Object> entry : this.properties.entrySet()) {
String key = entry.getKey();
Object value = entry.getValue();
E.checkArgumentNotNull(value, "Not allowed to set value of " +
"property '%s' to null for edge '%s'",
key, this.id);
}
}
public Object[] properties() {
return API.properties(this.properties);
}
@Override
public String toString() {
return String.format("JsonEdge{label=%s, " +
"source-vertex=%s, source-vertex-label=%s, " +
"target-vertex=%s, target-vertex-label=%s, " +
"properties=%s}",
this.label, this.source, this.sourceLabel,
this.target, this.targetLabel,
this.properties);
}
}
}

View File

@ -0,0 +1,314 @@
/*
* Copyright 2017 HugeGraph Authors
*
* 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.
*/
package com.baidu.hugegraph.api.graph;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import javax.inject.Singleton;
import javax.ws.rs.Consumes;
import javax.ws.rs.DELETE;
import javax.ws.rs.DefaultValue;
import javax.ws.rs.GET;
import javax.ws.rs.POST;
import javax.ws.rs.PUT;
import javax.ws.rs.Path;
import javax.ws.rs.PathParam;
import javax.ws.rs.Produces;
import javax.ws.rs.QueryParam;
import javax.ws.rs.core.Context;
import org.apache.tinkerpop.gremlin.process.traversal.dsl.graph.GraphTraversal;
import org.apache.tinkerpop.gremlin.structure.T;
import org.apache.tinkerpop.gremlin.structure.Vertex;
import org.slf4j.Logger;
import com.baidu.hugegraph.HugeGraph;
import com.baidu.hugegraph.api.API;
import com.baidu.hugegraph.api.filter.CompressInterceptor.Compress;
import com.baidu.hugegraph.api.filter.DecompressInterceptor.Decompress;
import com.baidu.hugegraph.api.filter.StatusFilter.Status;
import com.baidu.hugegraph.api.schema.Checkable;
import com.baidu.hugegraph.backend.id.Id;
import com.baidu.hugegraph.config.HugeConfig;
import com.baidu.hugegraph.config.ServerOptions;
import com.baidu.hugegraph.core.GraphManager;
import com.baidu.hugegraph.schema.PropertyKey;
import com.baidu.hugegraph.schema.VertexLabel;
import com.baidu.hugegraph.server.RestServer;
import com.baidu.hugegraph.structure.HugeVertex;
import com.baidu.hugegraph.type.HugeType;
import com.baidu.hugegraph.util.E;
import com.baidu.hugegraph.util.JsonUtil;
import com.baidu.hugegraph.util.Log;
import com.codahale.metrics.annotation.Timed;
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
import com.fasterxml.jackson.annotation.JsonProperty;
@Path("graphs/{graph}/graph/vertices")
@Singleton
public class VertexAPI extends BatchAPI {
private static final Logger LOG = Log.logger(RestServer.class);
@POST
@Timed
@Status(Status.CREATED)
@Consumes(APPLICATION_JSON)
@Produces(APPLICATION_JSON_WITH_CHARSET)
public String create(@Context GraphManager manager,
@PathParam("graph") String graph,
JsonVertex jsonVertex) {
LOG.debug("Graph [{}] create vertex: {}", graph, jsonVertex);
checkCreatingBody(jsonVertex);
HugeGraph g = graph(manager, graph);
Vertex vertex = commit(g, () -> g.addVertex(jsonVertex.properties()));
return manager.serializer(g).writeVertex(vertex);
}
@POST
@Timed
@Decompress
@Path("batch")
@Status(Status.CREATED)
@Consumes(APPLICATION_JSON)
@Produces(APPLICATION_JSON_WITH_CHARSET)
public List<String> create(@Context HugeConfig config,
@Context GraphManager manager,
@PathParam("graph") String graph,
List<JsonVertex> jsonVertices) {
LOG.debug("Graph [{}] create vertices: {}", graph, jsonVertices);
checkCreatingBody(jsonVertices);
HugeGraph g = graph(manager, graph);
checkBatchSize(g, jsonVertices);
return this.commit(config, g, jsonVertices.size(), () -> {
List<String> ids = new ArrayList<>(jsonVertices.size());
for (JsonVertex vertex : jsonVertices) {
ids.add(g.addVertex(vertex.properties()).id().toString());
}
return ids;
});
}
@PUT
@Timed
@Path("{id}")
@Consumes(APPLICATION_JSON)
@Produces(APPLICATION_JSON_WITH_CHARSET)
public String update(@Context GraphManager manager,
@PathParam("graph") String graph,
@PathParam("id") String idValue,
@QueryParam("action") String action,
JsonVertex jsonVertex) {
LOG.debug("Graph [{}] update vertex: {}", graph, jsonVertex);
checkUpdatingBody(jsonVertex);
Id id = checkAndParseVertexId(idValue);
// Parse action param
boolean append = checkAndParseAction(action);
HugeGraph g = graph(manager, graph);
HugeVertex vertex = (HugeVertex) g.vertices(id).next();
VertexLabel vertexLabel = vertex.schemaLabel();
for (String key : jsonVertex.properties.keySet()) {
PropertyKey pkey = g.propertyKey(key);
E.checkArgument(vertexLabel.properties().contains(pkey.id()),
"Can't update property for vertex '%s' because " +
"there is no property key '%s' in its vertex label",
id, key);
}
commit(g, () -> {
for (Map.Entry<String, Object> e :
jsonVertex.properties.entrySet()) {
String key = e.getKey();
Object value = e.getValue();
if (append) {
vertex.property(key, value);
} else {
vertex.property(key).remove();
}
}
});
return manager.serializer(g).writeVertex(vertex);
}
@GET
@Timed
@Compress
@Produces(APPLICATION_JSON_WITH_CHARSET)
public String list(@Context GraphManager manager,
@PathParam("graph") String graph,
@QueryParam("label") String label,
@QueryParam("properties") String properties,
@QueryParam("offset") @DefaultValue("0") long offset,
@QueryParam("page") String page,
@QueryParam("limit") @DefaultValue("100") long limit) {
LOG.debug("Graph [{}] query vertices by label: {}, properties: {}, " +
"offset: {}, page: {}, limit: {}",
graph, label, properties, offset, page, limit);
if (page != null) {
E.checkArgument(label == null && properties == null && offset == 0,
"Not support quering vertices based on paging " +
"and [label, properties, offset] together");
}
Map<String, Object> props = parseProperties(properties);
HugeGraph g = graph(manager, graph);
GraphTraversal<Vertex, Vertex> traversal = g.traversal().V();
if (label != null) {
traversal = traversal.hasLabel(label);
}
for (Map.Entry<String, Object> entry : props.entrySet()) {
traversal = traversal.has(entry.getKey(), entry.getValue());
}
if (page == null) {
traversal = traversal.range(offset, offset + limit);
} else {
traversal = traversal.has("~page", page).limit(limit);
}
return manager.serializer(g).writeVertices(traversal, page != null);
}
@GET
@Timed
@Path("{id}")
@Produces(APPLICATION_JSON_WITH_CHARSET)
public String get(@Context GraphManager manager,
@PathParam("graph") String graph,
@PathParam("id") String idValue) {
LOG.debug("Graph [{}] get vertex by id '{}'", graph, idValue);
Id id = checkAndParseVertexId(idValue);
HugeGraph g = graph(manager, graph);
Iterator<Vertex> vertices = g.vertices(id);
checkExist(vertices, HugeType.VERTEX, idValue);
return manager.serializer(g).writeVertex(vertices.next());
}
@DELETE
@Timed
@Path("{id}")
@Consumes(APPLICATION_JSON)
public void delete(@Context GraphManager manager,
@PathParam("graph") String graph,
@PathParam("id") String idValue) {
LOG.debug("Graph [{}] remove vertex by id '{}'", graph, idValue);
Id id = checkAndParseVertexId(idValue);
HugeGraph g = graph(manager, graph);
// TODO: add removeVertex(id) to improve
commit(g, () -> {
Iterator<Vertex> itor = g.vertices(id);
E.checkArgument(itor.hasNext(),
"No such vertex with id: '%s'", idValue);
itor.next().remove();
});
}
public static Id checkAndParseVertexId(String idValue) {
if (idValue == null) {
return null;
}
try {
Object id = JsonUtil.fromJson(idValue, Object.class);
return HugeVertex.getIdValue(id);
} catch (Exception e) {
throw new IllegalArgumentException(String.format(
"The vertex id must be formatted as String or " +
"Number, but got '%s'", idValue));
}
}
private static void checkBatchSize(HugeGraph g, List<JsonVertex> vertices) {
int max = g.configuration().get(ServerOptions.MAX_VERTICES_PER_BATCH);
if (vertices.size() > max) {
throw new IllegalArgumentException(String.format(
"Too many counts of vertices for one time post, " +
"the maximum number is '%s'", max));
}
}
@JsonIgnoreProperties(value = {"type"})
private static class JsonVertex implements Checkable {
@JsonProperty("id")
public Object id;
@JsonProperty("label")
public String label;
@JsonProperty("properties")
public Map<String, Object> properties;
@JsonProperty("type")
public String type;
@Override
public void checkCreate(boolean isBatch) {
E.checkArgumentNotNull(this.label,
"The label of vertex can't be null");
this.checkUpdate();
}
@Override
public void checkUpdate() {
E.checkArgumentNotNull(this.properties,
"The properties of vertex can't be null");
for (Map.Entry<String, Object> e : this.properties.entrySet()) {
String key = e.getKey();
Object value = e.getValue();
E.checkArgumentNotNull(value, "Not allowed to set value of " +
"property '%s' to null for vertex '%s'",
key, this.id);
}
}
public Object[] properties() {
Object[] props = API.properties(this.properties);
List<Object> list = new ArrayList<>(Arrays.asList(props));
list.add(T.label);
list.add(this.label);
if (this.id != null) {
list.add(T.id);
list.add(this.id);
}
return list.toArray();
}
@Override
public String toString() {
return String.format("JsonVertex{label=%s, properties=%s}",
this.label, this.properties);
}
}
}

View File

@ -0,0 +1,163 @@
/*
* Copyright 2017 HugeGraph Authors
*
* 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.
*/
package com.baidu.hugegraph.api.job;
import java.util.HashMap;
import java.util.Map;
import javax.inject.Singleton;
import javax.ws.rs.Consumes;
import javax.ws.rs.POST;
import javax.ws.rs.Path;
import javax.ws.rs.PathParam;
import javax.ws.rs.Produces;
import javax.ws.rs.core.Context;
import org.slf4j.Logger;
import com.baidu.hugegraph.HugeGraph;
import com.baidu.hugegraph.api.API;
import com.baidu.hugegraph.api.filter.StatusFilter.Status;
import com.baidu.hugegraph.api.schema.Checkable;
import com.baidu.hugegraph.backend.id.Id;
import com.baidu.hugegraph.backend.query.Query;
import com.baidu.hugegraph.core.GraphManager;
import com.baidu.hugegraph.job.Job;
import com.baidu.hugegraph.job.JobBuilder;
import com.baidu.hugegraph.server.RestServer;
import com.baidu.hugegraph.traversal.optimize.HugeScriptTraversal;
import com.baidu.hugegraph.util.E;
import com.baidu.hugegraph.util.JsonUtil;
import com.baidu.hugegraph.util.Log;
import com.codahale.metrics.annotation.Timed;
import jersey.repackaged.com.google.common.collect.ImmutableMap;
@Path("graphs/{graph}/jobs/gremlin")
@Singleton
public class GremlinAPI extends API {
private static final Logger LOG = Log.logger(RestServer.class);
@POST
@Timed
@Status(Status.CREATED)
@Consumes(APPLICATION_JSON)
@Produces(APPLICATION_JSON_WITH_CHARSET)
public Map<String, Id> post(@Context GraphManager manager,
@PathParam("graph") String graph,
GremlinRequest request) {
LOG.debug("Graph [{}] schedule gremlin job: {}", graph, request);
checkCreatingBody(request);
HugeGraph g = graph(manager, graph);
request.aliase(graph, "graph");
JobBuilder builder = JobBuilder.of(g).name(request.name())
.input(request.toJson())
.job(new GremlinJob());
return ImmutableMap.of("task_id", builder.schedule());
}
public static class GremlinJob extends Job<Object> {
public static final String TASK_TYPE = "gremlin";
@Override
public String type() {
return TASK_TYPE;
}
@Override
public Object call() throws Exception {
GremlinRequest input = GremlinRequest.fromJson(this.task().input());
HugeScriptTraversal<?, ?> st;
st = new HugeScriptTraversal<>(this.graph().traversal(),
input.language(), input.gremlin(),
input.bindings(), input.aliases());
long count = 0;
long capacity = Query.defaultCapacity(Query.NO_CAPACITY);
try {
while (st.hasNext()) {
st.next();
++count;
Thread.yield();
}
} finally {
Query.defaultCapacity(capacity);
st.close();
this.graph().tx().commit();
}
Object result = st.result();
return result != null ? result : count;
}
}
private static class GremlinRequest implements Checkable {
// See org.apache.tinkerpop.gremlin.server.channel.HttpChannelizer
public String gremlin;
public Map<String, Object> bindings = new HashMap<>();
public String language;
public Map<String, String> aliases = new HashMap<>();
public void aliase(String key, String value) {
this.aliases.put(key, value);
}
public Map<String, Object> bindings() {
return this.bindings;
}
public String language() {
return this.language;
}
public String gremlin() {
return this.gremlin;
}
public Map<String, String> aliases() {
return this.aliases;
}
public String name() {
// Get the first line of script as the name
return this.gremlin.split("\r\n|\r|\n", 2)[0];
}
@Override
public void checkCreate(boolean isBatch) {
E.checkArgumentNotNull(this.gremlin,
"The gremlin script can't be null");
E.checkArgument(this.aliases == null || this.aliases.isEmpty(),
"There is no need to pass gremlin aliases");
}
public String toJson() {
return JsonUtil.toJson(this);
}
public static GremlinRequest fromJson(String json) {
return JsonUtil.fromJson(json, GremlinRequest.class);
}
}
}

View File

@ -1,48 +1,47 @@
/*
* Copyright 2017 HugeGraph Authors
*
* 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
* 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.
* 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.hugegraph.api.job;
package com.baidu.hugegraph.api.job;
import java.util.Map;
import org.apache.hugegraph.HugeGraph;
import org.apache.hugegraph.api.API;
import org.apache.hugegraph.api.filter.RedirectFilter;
import org.apache.hugegraph.api.filter.StatusFilter.Status;
import org.apache.hugegraph.backend.id.Id;
import org.apache.hugegraph.core.GraphManager;
import org.apache.hugegraph.util.Log;
import javax.annotation.security.RolesAllowed;
import javax.inject.Singleton;
import javax.ws.rs.PUT;
import javax.ws.rs.Path;
import javax.ws.rs.PathParam;
import javax.ws.rs.Produces;
import javax.ws.rs.core.Context;
import org.slf4j.Logger;
import com.baidu.hugegraph.HugeGraph;
import com.baidu.hugegraph.api.API;
import com.baidu.hugegraph.api.filter.StatusFilter.Status;
import com.baidu.hugegraph.backend.id.Id;
import com.baidu.hugegraph.core.GraphManager;
import com.baidu.hugegraph.util.Log;
import com.codahale.metrics.annotation.Timed;
import com.google.common.collect.ImmutableMap;
import io.swagger.v3.oas.annotations.tags.Tag;
import jakarta.annotation.security.RolesAllowed;
import jakarta.inject.Singleton;
import jakarta.ws.rs.PUT;
import jakarta.ws.rs.Path;
import jakarta.ws.rs.PathParam;
import jakarta.ws.rs.Produces;
import jakarta.ws.rs.core.Context;
@Path("graphs/{graph}/jobs/rebuild")
@Singleton
@Tag(name = "RebuildAPI")
public class RebuildAPI extends API {
private static final Logger LOG = Log.logger(RebuildAPI.class);
@ -52,8 +51,7 @@ public class RebuildAPI extends API {
@Path("vertexlabels/{name}")
@Status(Status.ACCEPTED)
@Produces(APPLICATION_JSON_WITH_CHARSET)
@RolesAllowed({"admin", "$owner=$graph $action=index_write"})
@RedirectFilter.RedirectMasterRole
@RolesAllowed({"admin", "$owner=graph"})
public Map<String, Id> vertexLabelRebuild(@Context GraphManager manager,
@PathParam("graph") String graph,
@PathParam("name") String name) {
@ -69,8 +67,7 @@ public class RebuildAPI extends API {
@Path("edgelabels/{name}")
@Status(Status.ACCEPTED)
@Produces(APPLICATION_JSON_WITH_CHARSET)
@RolesAllowed({"admin", "$owner=$graph $action=index_write"})
@RedirectFilter.RedirectMasterRole
@RolesAllowed({"admin", "$owner=graph"})
public Map<String, Id> edgeLabelRebuild(@Context GraphManager manager,
@PathParam("graph") String graph,
@PathParam("name") String name) {
@ -86,8 +83,7 @@ public class RebuildAPI extends API {
@Path("indexlabels/{name}")
@Status(Status.ACCEPTED)
@Produces(APPLICATION_JSON_WITH_CHARSET)
@RolesAllowed({"admin", "$owner=$graph $action=index_write"})
@RedirectFilter.RedirectMasterRole
@RolesAllowed({"admin", "$owner=graph"})
public Map<String, Id> indexLabelRebuild(@Context GraphManager manager,
@PathParam("graph") String graph,
@PathParam("name") String name) {
@ -97,4 +93,4 @@ public class RebuildAPI extends API {
return ImmutableMap.of("task_id",
g.schema().indexLabel(name).rebuild());
}
}
}

View File

@ -0,0 +1,132 @@
/*
* Copyright 2017 HugeGraph Authors
*
* 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.
*/
package com.baidu.hugegraph.api.job;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import javax.inject.Singleton;
import javax.ws.rs.BadRequestException;
import javax.ws.rs.DELETE;
import javax.ws.rs.DefaultValue;
import javax.ws.rs.GET;
import javax.ws.rs.Path;
import javax.ws.rs.PathParam;
import javax.ws.rs.Produces;
import javax.ws.rs.QueryParam;
import javax.ws.rs.core.Context;
import org.slf4j.Logger;
import com.baidu.hugegraph.HugeGraph;
import com.baidu.hugegraph.api.API;
import com.baidu.hugegraph.backend.id.IdGenerator;
import com.baidu.hugegraph.core.GraphManager;
import com.baidu.hugegraph.server.RestServer;
import com.baidu.hugegraph.task.HugeTask;
import com.baidu.hugegraph.task.HugeTaskScheduler;
import com.baidu.hugegraph.task.Status;
import com.baidu.hugegraph.util.Log;
import com.codahale.metrics.annotation.Timed;
import com.google.common.collect.ImmutableMap;
@Path("graphs/{graph}/tasks")
@Singleton
public class TaskAPI extends API {
private static final Logger LOG = Log.logger(RestServer.class);
@GET
@Timed
@Produces(APPLICATION_JSON_WITH_CHARSET)
public Map<String, List<Object>> list(@Context GraphManager manager,
@PathParam("graph") String graph,
@QueryParam("status") String status,
@QueryParam("limit")
@DefaultValue("100") long limit) {
LOG.debug("Graph [{}] list tasks with status {}, limit {}",
graph, status, limit);
HugeGraph g = graph(manager, graph);
HugeTaskScheduler scheduler = g.taskScheduler();
Iterator<HugeTask<Object>> itor;
if (status == null) {
itor = scheduler.findAllTask(limit);
} else {
itor = scheduler.findTask(parseStatus(status), limit);
}
List<Object> tasks = new ArrayList<>();
while (itor.hasNext()) {
tasks.add(itor.next().asMap());
}
return ImmutableMap.of("tasks", tasks);
}
@GET
@Timed
@Path("{id}")
@Produces(APPLICATION_JSON_WITH_CHARSET)
public Map<String, Object> get(@Context GraphManager manager,
@PathParam("graph") String graph,
@PathParam("id") long id) {
LOG.debug("Graph [{}] get task: {}", graph, id);
HugeGraph g = graph(manager, graph);
HugeTaskScheduler scheduler = g.taskScheduler();
return scheduler.task(IdGenerator.of(id)).asMap();
}
@DELETE
@Timed
@Path("{id}")
public void delete(@Context GraphManager manager,
@PathParam("graph") String graph,
@PathParam("id") long id) {
LOG.debug("Graph [{}] delete task: {}", graph, id);
HugeGraph g = graph(manager, graph);
HugeTaskScheduler scheduler = g.taskScheduler();
HugeTask task = scheduler.task(IdGenerator.of(id));
if (task.completed()) {
scheduler.deleteTask(IdGenerator.of(id));
} else {
throw new BadRequestException(String.format(
"Can't delete task '%s' with unstable status '%s'",
id, task.status()));
}
}
private static Status parseStatus(String status) {
try {
return Status.valueOf(status);
} catch (Exception e) {
throw new IllegalArgumentException(String.format(
"Status value must be in [UNKNOWN, NEW, QUEUED, " +
"RESTORING, RUNNING, SUCCESS, CANCELLED, FAILED], " +
"but got '%s'", status));
}
}
}

View File

@ -0,0 +1,121 @@
/*
* Copyright 2017 HugeGraph Authors
*
* 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.
*/
package com.baidu.hugegraph.api.metrics;
import static java.util.concurrent.TimeUnit.MILLISECONDS;
import static java.util.concurrent.TimeUnit.SECONDS;
import java.util.LinkedHashMap;
import java.util.Map;
import javax.annotation.security.RolesAllowed;
import javax.inject.Singleton;
import javax.ws.rs.GET;
import javax.ws.rs.Path;
import javax.ws.rs.Produces;
import com.baidu.hugegraph.api.API;
import com.baidu.hugegraph.metric.ServerReporter;
import com.baidu.hugegraph.metric.SystemMetrics;
import com.baidu.hugegraph.util.JsonUtil;
import com.codahale.metrics.Metric;
import com.codahale.metrics.json.MetricsModule;
@Singleton
@Path("metrics")
public class MetricsAPI extends API {
private SystemMetrics systemMetrics;
static {
JsonUtil.registerModule(new MetricsModule(SECONDS, MILLISECONDS, false));
}
public MetricsAPI() {
this.systemMetrics = new SystemMetrics();
}
@GET
@Path("system")
@Produces(APPLICATION_JSON_WITH_CHARSET)
@RolesAllowed("admin")
public String system() {
return JsonUtil.toJson(this.systemMetrics.metrics());
}
@GET
@Produces(APPLICATION_JSON_WITH_CHARSET)
@RolesAllowed("admin")
public String all() {
ServerReporter reporter = ServerReporter.instance();
Map<String, Map<String, ? extends Metric>> result = new LinkedHashMap<>();
result.put("gauges", reporter.gauges());
result.put("counters", reporter.counters());
result.put("histograms", reporter.histograms());
result.put("meters", reporter.meters());
result.put("timers", reporter.timers());
return JsonUtil.toJson(result);
}
@GET
@Path("gauges")
@Produces(APPLICATION_JSON_WITH_CHARSET)
@RolesAllowed("admin")
public String gauges() {
ServerReporter reporter = ServerReporter.instance();
return JsonUtil.toJson(reporter.gauges());
}
@GET
@Path("counters")
@Produces(APPLICATION_JSON_WITH_CHARSET)
@RolesAllowed("admin")
public String counters() {
ServerReporter reporter = ServerReporter.instance();
return JsonUtil.toJson(reporter.counters());
}
@GET
@Path("histograms")
@Produces(APPLICATION_JSON_WITH_CHARSET)
@RolesAllowed("admin")
public String histograms() {
ServerReporter reporter = ServerReporter.instance();
return JsonUtil.toJson(reporter.histograms());
}
@GET
@Path("meters")
@Produces(APPLICATION_JSON_WITH_CHARSET)
@RolesAllowed("admin")
public String meters() {
ServerReporter reporter = ServerReporter.instance();
return JsonUtil.toJson(reporter.meters());
}
@GET
@Path("times")
@Produces(APPLICATION_JSON_WITH_CHARSET)
@RolesAllowed("admin")
public String times() {
ServerReporter reporter = ServerReporter.instance();
return JsonUtil.toJson(reporter.timers());
}
}

View File

@ -0,0 +1,10 @@
package com.baidu.hugegraph.api.schema;
public interface Checkable {
public void checkCreate(boolean isBatch);
public default void checkUpdate() {
this.checkCreate(false);
}
}

View File

@ -1,65 +1,56 @@
/*
* Copyright 2017 HugeGraph Authors
*
* 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
* 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.
* 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.hugegraph.api.schema;
package com.baidu.hugegraph.api.schema;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Map;
import org.apache.commons.collections.CollectionUtils;
import org.apache.hugegraph.HugeGraph;
import org.apache.hugegraph.api.API;
import org.apache.hugegraph.api.filter.RedirectFilter;
import org.apache.hugegraph.api.filter.StatusFilter.Status;
import org.apache.hugegraph.backend.id.Id;
import org.apache.hugegraph.core.GraphManager;
import org.apache.hugegraph.define.Checkable;
import org.apache.hugegraph.schema.EdgeLabel;
import org.apache.hugegraph.schema.Userdata;
import org.apache.hugegraph.type.define.Frequency;
import org.apache.hugegraph.type.define.GraphMode;
import org.apache.hugegraph.util.E;
import org.apache.hugegraph.util.Log;
import javax.inject.Singleton;
import javax.ws.rs.Consumes;
import javax.ws.rs.DELETE;
import javax.ws.rs.GET;
import javax.ws.rs.POST;
import javax.ws.rs.PUT;
import javax.ws.rs.Path;
import javax.ws.rs.PathParam;
import javax.ws.rs.Produces;
import javax.ws.rs.QueryParam;
import javax.ws.rs.core.Context;
import org.slf4j.Logger;
import com.baidu.hugegraph.HugeGraph;
import com.baidu.hugegraph.api.API;
import com.baidu.hugegraph.api.filter.StatusFilter.Status;
import com.baidu.hugegraph.backend.id.Id;
import com.baidu.hugegraph.core.GraphManager;
import com.baidu.hugegraph.schema.EdgeLabel;
import com.baidu.hugegraph.type.define.Frequency;
import com.baidu.hugegraph.util.E;
import com.baidu.hugegraph.util.Log;
import com.codahale.metrics.annotation.Timed;
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
import com.fasterxml.jackson.annotation.JsonProperty;
import com.google.common.collect.ImmutableMap;
import io.swagger.v3.oas.annotations.tags.Tag;
import jakarta.annotation.security.RolesAllowed;
import jakarta.inject.Singleton;
import jakarta.ws.rs.Consumes;
import jakarta.ws.rs.DELETE;
import jakarta.ws.rs.GET;
import jakarta.ws.rs.POST;
import jakarta.ws.rs.PUT;
import jakarta.ws.rs.Path;
import jakarta.ws.rs.PathParam;
import jakarta.ws.rs.Produces;
import jakarta.ws.rs.QueryParam;
import jakarta.ws.rs.core.Context;
@Path("graphs/{graph}/schema/edgelabels")
@Singleton
@Tag(name = "EdgeLabelAPI")
public class EdgeLabelAPI extends API {
private static final Logger LOG = Log.logger(EdgeLabelAPI.class);
@ -69,8 +60,6 @@ public class EdgeLabelAPI extends API {
@Status(Status.CREATED)
@Consumes(APPLICATION_JSON)
@Produces(APPLICATION_JSON_WITH_CHARSET)
@RolesAllowed({"admin", "$owner=$graph $action=edge_label_write"})
@RedirectFilter.RedirectMasterRole
public String create(@Context GraphManager manager,
@PathParam("graph") String graph,
JsonEdgeLabel jsonEdgeLabel) {
@ -88,8 +77,6 @@ public class EdgeLabelAPI extends API {
@Path("{name}")
@Consumes(APPLICATION_JSON)
@Produces(APPLICATION_JSON_WITH_CHARSET)
@RolesAllowed({"admin", "$owner=$graph $action=edge_label_write"})
@RedirectFilter.RedirectMasterRole
public String update(@Context GraphManager manager,
@PathParam("graph") String graph,
@PathParam("name") String name,
@ -114,27 +101,12 @@ public class EdgeLabelAPI extends API {
@GET
@Timed
@Produces(APPLICATION_JSON_WITH_CHARSET)
@RolesAllowed({"admin", "$owner=$graph $action=edge_label_read"})
public String list(@Context GraphManager manager,
@PathParam("graph") String graph,
@QueryParam("names") List<String> names) {
boolean listAll = CollectionUtils.isEmpty(names);
if (listAll) {
LOG.debug("Graph [{}] list edge labels", graph);
} else {
LOG.debug("Graph [{}] get edge labels by names {}", graph, names);
}
@PathParam("graph") String graph) {
LOG.debug("Graph [{}] get edge labels", graph);
HugeGraph g = graph(manager, graph);
List<EdgeLabel> labels;
if (listAll) {
labels = g.schema().getEdgeLabels();
} else {
labels = new ArrayList<>(names.size());
for (String name : names) {
labels.add(g.schema().getEdgeLabel(name));
}
}
List<EdgeLabel> labels = g.schema().getEdgeLabels();
return manager.serializer(g).writeEdgeLabels(labels);
}
@ -142,7 +114,6 @@ public class EdgeLabelAPI extends API {
@Timed
@Path("{name}")
@Produces(APPLICATION_JSON_WITH_CHARSET)
@RolesAllowed({"admin", "$owner=$graph $action=edge_label_read"})
public String get(@Context GraphManager manager,
@PathParam("graph") String graph,
@PathParam("name") String name) {
@ -159,8 +130,6 @@ public class EdgeLabelAPI extends API {
@Status(Status.ACCEPTED)
@Consumes(APPLICATION_JSON)
@Produces(APPLICATION_JSON_WITH_CHARSET)
@RolesAllowed({"admin", "$owner=$graph $action=edge_label_delete"})
@RedirectFilter.RedirectMasterRole
public Map<String, Id> delete(@Context GraphManager manager,
@PathParam("graph") String graph,
@PathParam("name") String name) {
@ -176,7 +145,6 @@ public class EdgeLabelAPI extends API {
/**
* JsonEdgeLabel is only used to receive create and append requests
*/
@JsonIgnoreProperties(value = {"index_labels", "status"})
private static class JsonEdgeLabel implements Checkable {
@JsonProperty("id")
@ -195,34 +163,21 @@ public class EdgeLabelAPI extends API {
public String[] sortKeys;
@JsonProperty("nullable_keys")
public String[] nullableKeys;
@JsonProperty("ttl")
public long ttl;
@JsonProperty("ttl_start_time")
public String ttlStartTime;
@JsonProperty("enable_label_index")
public Boolean enableLabelIndex;
@JsonProperty("user_data")
public Userdata userdata;
public Map<String, Object> userdata;
@JsonProperty("check_exist")
public Boolean checkExist;
@Override
public void checkCreate(boolean isBatch) {
E.checkArgumentNotNull(this.name, "The name of edge label can't be null");
E.checkArgumentNotNull(this.name,
"The name of edge label can't be null");
}
private EdgeLabel.Builder convert2Builder(HugeGraph g) {
EdgeLabel.Builder builder = g.schema().edgeLabel(this.name);
if (this.id != 0) {
E.checkArgument(this.id > 0,
"Only positive number can be assign as " +
"edge label id");
E.checkArgument(g.mode() == GraphMode.RESTORING,
"Only accept edge label id when graph in " +
"RESTORING mode, but '%s' is in mode '%s'",
g, g.mode());
builder.id(this.id);
}
if (this.sourceLabel != null) {
builder.sourceLabel(this.sourceLabel);
}
@ -250,28 +205,17 @@ public class EdgeLabelAPI extends API {
if (this.checkExist != null) {
builder.checkExist(this.checkExist);
}
if (this.ttl != 0) {
builder.ttl(this.ttl);
}
if (this.ttlStartTime != null) {
E.checkArgument(this.ttl > 0,
"Only set ttlStartTime when ttl is " +
"positive, but got ttl: %s", this.ttl);
builder.ttlStartTime(this.ttlStartTime);
}
return builder;
}
@Override
public String toString() {
return String.format("JsonEdgeLabel{" +
"name=%s, sourceLabel=%s, targetLabel=%s, frequency=%s, " +
"sortKeys=%s, nullableKeys=%s, properties=%s, ttl=%s, " +
"ttlStartTime=%s}",
this.name, this.sourceLabel, this.targetLabel,
this.frequency, Arrays.toString(this.sortKeys),
Arrays.toString(this.nullableKeys),
Arrays.toString(this.properties), this.ttl, this.ttlStartTime);
"name=%s, sourceLabel=%s, targetLabel=%s, frequency=%s, " +
"sortKeys=%s, nullableKeys=%s, properties=%s}",
this.name, this.sourceLabel, this.targetLabel,
this.frequency, this.sortKeys, this.nullableKeys,
this.properties);
}
}
}

View File

@ -0,0 +1,177 @@
/*
* Copyright 2017 HugeGraph Authors
*
* 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.
*/
package com.baidu.hugegraph.api.schema;
import java.util.List;
import java.util.Map;
import javax.inject.Singleton;
import javax.ws.rs.Consumes;
import javax.ws.rs.DELETE;
import javax.ws.rs.GET;
import javax.ws.rs.POST;
import javax.ws.rs.Path;
import javax.ws.rs.PathParam;
import javax.ws.rs.Produces;
import javax.ws.rs.core.Context;
import org.slf4j.Logger;
import com.baidu.hugegraph.HugeGraph;
import com.baidu.hugegraph.api.API;
import com.baidu.hugegraph.api.filter.StatusFilter.Status;
import com.baidu.hugegraph.backend.id.Id;
import com.baidu.hugegraph.core.GraphManager;
import com.baidu.hugegraph.schema.IndexLabel;
import com.baidu.hugegraph.type.HugeType;
import com.baidu.hugegraph.type.define.IndexType;
import com.baidu.hugegraph.util.E;
import com.baidu.hugegraph.util.Log;
import com.codahale.metrics.annotation.Timed;
import com.fasterxml.jackson.annotation.JsonProperty;
import com.google.common.collect.ImmutableMap;
@Path("graphs/{graph}/schema/indexlabels")
@Singleton
public class IndexLabelAPI extends API {
private static final Logger LOG = Log.logger(IndexLabelAPI.class);
@POST
@Timed
@Status(Status.ACCEPTED)
@Consumes(APPLICATION_JSON)
@Produces(APPLICATION_JSON_WITH_CHARSET)
public String create(@Context GraphManager manager,
@PathParam("graph") String graph,
JsonIndexLabel jsonIndexLabel) {
LOG.debug("Graph [{}] create index label: {}", graph, jsonIndexLabel);
checkCreatingBody(jsonIndexLabel);
HugeGraph g = graph(manager, graph);
IndexLabel.Builder builder = jsonIndexLabel.convert2Builder(g);
IndexLabel indexLabel = builder.create();
return manager.serializer(g).writeIndexlabel(indexLabel);
}
@GET
@Timed
@Produces(APPLICATION_JSON_WITH_CHARSET)
public String list(@Context GraphManager manager,
@PathParam("graph") String graph) {
LOG.debug("Graph [{}] get edge labels", graph);
HugeGraph g = graph(manager, graph);
List<IndexLabel> labels = g.schema().getIndexLabels();
return manager.serializer(g).writeIndexlabels(labels);
}
@GET
@Timed
@Path("{name}")
@Produces(APPLICATION_JSON_WITH_CHARSET)
public String get(@Context GraphManager manager,
@PathParam("graph") String graph,
@PathParam("name") String name) {
LOG.debug("Graph [{}] get edge label by name '{}'", graph, name);
HugeGraph g = graph(manager, graph);
IndexLabel indexLabel = g.schema().getIndexLabel(name);
return manager.serializer(g).writeIndexlabel(indexLabel);
}
@DELETE
@Timed
@Path("{name}")
@Status(Status.ACCEPTED)
@Consumes(APPLICATION_JSON)
@Produces(APPLICATION_JSON_WITH_CHARSET)
public Map<String, Id> delete(@Context GraphManager manager,
@PathParam("graph") String graph,
@PathParam("name") String name) {
LOG.debug("Graph [{}] remove index label by name '{}'", graph, name);
HugeGraph g = graph(manager, graph);
// Throw 404 if not exists
g.schema().getIndexLabel(name);
return ImmutableMap.of("task_id",
g.schema().indexLabel(name).remove());
}
/**
* JsonIndexLabel is only used to receive create and append requests
*/
private static class JsonIndexLabel implements Checkable {
@JsonProperty("id")
public long id;
@JsonProperty("name")
public String name;
@JsonProperty("base_type")
public HugeType baseType;
@JsonProperty("base_value")
public String baseValue;
@JsonProperty("index_type")
public IndexType indexType;
@JsonProperty("fields")
public String[] fields;
@JsonProperty("check_exist")
public Boolean checkExist;
@Override
public void checkCreate(boolean isBatch) {
E.checkArgumentNotNull(this.name,
"The name of index label can't be null");
E.checkArgumentNotNull(this.baseType,
"The base type of index label '%s' " +
"can't be null", this.name);
E.checkArgument(this.baseType == HugeType.VERTEX_LABEL ||
this.baseType == HugeType.EDGE_LABEL,
"The base type of index label '%s' can only be " +
"either VERTEX_LABEL or EDGE_LABEL", this.name);
E.checkArgumentNotNull(this.baseValue,
"The base value of index label '%s' " +
"can't be null", this.name);
}
private IndexLabel.Builder convert2Builder(HugeGraph g) {
IndexLabel.Builder builder = g.schema().indexLabel(this.name);
builder.on(this.baseType, this.baseValue);
if (this.indexType != null) {
builder.indexType(this.indexType);
}
if (this.fields != null) {
builder.by(this.fields);
}
if (this.checkExist != null) {
builder.checkExist(this.checkExist);
}
return builder;
}
@Override
public String toString() {
return String.format("JsonIndexLabel{name=%s, baseType=%s," +
"baseValue=%s, indexType=%s, fields=%s}",
this.name, this.baseType, this.baseValue,
this.indexType, this.fields);
}
}
}

View File

@ -0,0 +1,199 @@
/*
* Copyright 2017 HugeGraph Authors
*
* 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.
*/
package com.baidu.hugegraph.api.schema;
import java.util.List;
import java.util.Map;
import javax.inject.Singleton;
import javax.ws.rs.Consumes;
import javax.ws.rs.DELETE;
import javax.ws.rs.GET;
import javax.ws.rs.POST;
import javax.ws.rs.PUT;
import javax.ws.rs.Path;
import javax.ws.rs.PathParam;
import javax.ws.rs.Produces;
import javax.ws.rs.QueryParam;
import javax.ws.rs.core.Context;
import org.slf4j.Logger;
import com.baidu.hugegraph.HugeGraph;
import com.baidu.hugegraph.api.API;
import com.baidu.hugegraph.api.filter.StatusFilter.Status;
import com.baidu.hugegraph.core.GraphManager;
import com.baidu.hugegraph.schema.PropertyKey;
import com.baidu.hugegraph.type.define.Cardinality;
import com.baidu.hugegraph.type.define.DataType;
import com.baidu.hugegraph.util.E;
import com.baidu.hugegraph.util.Log;
import com.codahale.metrics.annotation.Timed;
import com.fasterxml.jackson.annotation.JsonProperty;
@Path("graphs/{graph}/schema/propertykeys")
@Singleton
public class PropertyKeyAPI extends API {
private static final Logger LOG = Log.logger(PropertyKeyAPI.class);
@POST
@Timed
@Status(Status.CREATED)
@Consumes(APPLICATION_JSON)
@Produces(APPLICATION_JSON_WITH_CHARSET)
public String create(@Context GraphManager manager,
@PathParam("graph") String graph,
JsonPropertyKey jsonPropertyKey) {
LOG.debug("Graph [{}] create property key: {}",
graph, jsonPropertyKey);
checkCreatingBody(jsonPropertyKey);
HugeGraph g = graph(manager, graph);
PropertyKey.Builder builder = jsonPropertyKey.convert2Builder(g);
PropertyKey propertyKey = builder.create();
return manager.serializer(g).writePropertyKey(propertyKey);
}
@PUT
@Timed
@Path("{name}")
@Consumes(APPLICATION_JSON)
@Produces(APPLICATION_JSON_WITH_CHARSET)
public String update(@Context GraphManager manager,
@PathParam("graph") String graph,
@PathParam("name") String name,
@QueryParam("action") String action,
PropertyKeyAPI.JsonPropertyKey jsonPropertyKey) {
LOG.debug("Graph [{}] {} property key: {}",
graph, action, jsonPropertyKey);
checkUpdatingBody(jsonPropertyKey);
E.checkArgument(name.equals(jsonPropertyKey.name),
"The name in url(%s) and body(%s) are different",
name, jsonPropertyKey.name);
// Parse action parameter
boolean append = checkAndParseAction(action);
HugeGraph g = graph(manager, graph);
PropertyKey.Builder builder = jsonPropertyKey.convert2Builder(g);
PropertyKey propertyKey = append ?
builder.append() :
builder.eliminate();
return manager.serializer(g).writePropertyKey(propertyKey);
}
@GET
@Timed
@Produces(APPLICATION_JSON_WITH_CHARSET)
public String list(@Context GraphManager manager,
@PathParam("graph") String graph) {
LOG.debug("Graph [{}] get property keys", graph);
HugeGraph g = graph(manager, graph);
List<PropertyKey> propKeys = g.schema().getPropertyKeys();
return manager.serializer(g).writePropertyKeys(propKeys);
}
@GET
@Timed
@Path("{name}")
@Produces(APPLICATION_JSON_WITH_CHARSET)
public String get(@Context GraphManager manager,
@PathParam("graph") String graph,
@PathParam("name") String name) {
LOG.debug("Graph [{}] get property key by name '{}'", graph, name);
HugeGraph g = graph(manager, graph);
PropertyKey propertyKey = g.schema().getPropertyKey(name);
return manager.serializer(g).writePropertyKey(propertyKey);
}
@DELETE
@Timed
@Path("{name}")
@Consumes(APPLICATION_JSON)
public void delete(@Context GraphManager manager,
@PathParam("graph") String graph,
@PathParam("name") String name) {
LOG.debug("Graph [{}] remove property key by name '{}'", graph, name);
HugeGraph g = graph(manager, graph);
// Throw 404 if not exists
g.schema().getPropertyKey(name);
g.schema().propertyKey(name).remove();
}
/**
* JsonPropertyKey is only used to receive create and append requests
*/
private static class JsonPropertyKey implements Checkable {
@JsonProperty("id")
public long id;
@JsonProperty("name")
public String name;
@JsonProperty("cardinality")
public Cardinality cardinality;
@JsonProperty("data_type")
public DataType dataType;
@JsonProperty("properties")
public String[] properties;
@JsonProperty("user_data")
public Map<String, Object> userdata;
@JsonProperty("check_exist")
public Boolean checkExist;
@Override
public void checkCreate(boolean isBatch) {
E.checkArgumentNotNull(this.name,
"The name of property key can't be null");
E.checkArgument(this.properties == null ||
this.properties.length == 0,
"Not allowed to pass properties when " +
"creating property key since it doesn't " +
"support meta properties currently");
}
private PropertyKey.Builder convert2Builder(HugeGraph g) {
PropertyKey.Builder builder = g.schema().propertyKey(this.name);
if (this.cardinality != null) {
builder.cardinality(this.cardinality);
}
if (this.dataType != null) {
builder.dataType(this.dataType);
}
if (this.userdata != null) {
builder.userdata(this.userdata);
}
if (this.checkExist != null) {
builder.checkExist(this.checkExist);
}
return builder;
}
@Override
public String toString() {
return String.format("JsonPropertyKey{name=%s, cardinality=%s, " +
"dataType=%s, properties=%s}",
this.name, this.cardinality,
this.dataType, this.properties);
}
}
}

View File

@ -1,65 +1,56 @@
/*
* Copyright 2017 HugeGraph Authors
*
* 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
* 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.
* 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.hugegraph.api.schema;
package com.baidu.hugegraph.api.schema;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Map;
import org.apache.commons.collections.CollectionUtils;
import org.apache.hugegraph.HugeGraph;
import org.apache.hugegraph.api.API;
import org.apache.hugegraph.api.filter.RedirectFilter;
import org.apache.hugegraph.api.filter.StatusFilter.Status;
import org.apache.hugegraph.backend.id.Id;
import org.apache.hugegraph.core.GraphManager;
import org.apache.hugegraph.define.Checkable;
import org.apache.hugegraph.schema.Userdata;
import org.apache.hugegraph.schema.VertexLabel;
import org.apache.hugegraph.type.define.GraphMode;
import org.apache.hugegraph.type.define.IdStrategy;
import org.apache.hugegraph.util.E;
import org.apache.hugegraph.util.Log;
import javax.inject.Singleton;
import javax.ws.rs.Consumes;
import javax.ws.rs.DELETE;
import javax.ws.rs.GET;
import javax.ws.rs.POST;
import javax.ws.rs.PUT;
import javax.ws.rs.Path;
import javax.ws.rs.PathParam;
import javax.ws.rs.Produces;
import javax.ws.rs.QueryParam;
import javax.ws.rs.core.Context;
import org.slf4j.Logger;
import com.baidu.hugegraph.HugeGraph;
import com.baidu.hugegraph.api.API;
import com.baidu.hugegraph.api.filter.StatusFilter.Status;
import com.baidu.hugegraph.backend.id.Id;
import com.baidu.hugegraph.core.GraphManager;
import com.baidu.hugegraph.schema.VertexLabel;
import com.baidu.hugegraph.type.define.IdStrategy;
import com.baidu.hugegraph.util.E;
import com.baidu.hugegraph.util.Log;
import com.codahale.metrics.annotation.Timed;
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
import com.fasterxml.jackson.annotation.JsonProperty;
import com.google.common.collect.ImmutableMap;
import io.swagger.v3.oas.annotations.tags.Tag;
import jakarta.annotation.security.RolesAllowed;
import jakarta.inject.Singleton;
import jakarta.ws.rs.Consumes;
import jakarta.ws.rs.DELETE;
import jakarta.ws.rs.GET;
import jakarta.ws.rs.POST;
import jakarta.ws.rs.PUT;
import jakarta.ws.rs.Path;
import jakarta.ws.rs.PathParam;
import jakarta.ws.rs.Produces;
import jakarta.ws.rs.QueryParam;
import jakarta.ws.rs.core.Context;
@Path("graphs/{graph}/schema/vertexlabels")
@Singleton
@Tag(name = "VertexLabelAPI")
public class VertexLabelAPI extends API {
private static final Logger LOG = Log.logger(VertexLabelAPI.class);
@ -69,8 +60,6 @@ public class VertexLabelAPI extends API {
@Status(Status.CREATED)
@Consumes(APPLICATION_JSON)
@Produces(APPLICATION_JSON_WITH_CHARSET)
@RolesAllowed({"admin", "$owner=$graph $action=vertex_label_write"})
@RedirectFilter.RedirectMasterRole
public String create(@Context GraphManager manager,
@PathParam("graph") String graph,
JsonVertexLabel jsonVertexLabel) {
@ -89,8 +78,6 @@ public class VertexLabelAPI extends API {
@Path("{name}")
@Consumes(APPLICATION_JSON)
@Produces(APPLICATION_JSON_WITH_CHARSET)
@RolesAllowed({"admin", "$owner=$graph $action=vertex_label_write"})
@RedirectFilter.RedirectMasterRole
public String update(@Context GraphManager manager,
@PathParam("graph") String graph,
@PathParam("name") String name,
@ -117,27 +104,12 @@ public class VertexLabelAPI extends API {
@GET
@Timed
@Produces(APPLICATION_JSON_WITH_CHARSET)
@RolesAllowed({"admin", "$owner=$graph $action=vertex_label_read"})
public String list(@Context GraphManager manager,
@PathParam("graph") String graph,
@QueryParam("names") List<String> names) {
boolean listAll = CollectionUtils.isEmpty(names);
if (listAll) {
LOG.debug("Graph [{}] list vertex labels", graph);
} else {
LOG.debug("Graph [{}] get vertex labels by names {}", graph, names);
}
@PathParam("graph") String graph) {
LOG.debug("Graph [{}] get vertex labels", graph);
HugeGraph g = graph(manager, graph);
List<VertexLabel> labels;
if (listAll) {
labels = g.schema().getVertexLabels();
} else {
labels = new ArrayList<>(names.size());
for (String name : names) {
labels.add(g.schema().getVertexLabel(name));
}
}
List<VertexLabel> labels = g.schema().getVertexLabels();
return manager.serializer(g).writeVertexLabels(labels);
}
@ -145,7 +117,6 @@ public class VertexLabelAPI extends API {
@Timed
@Path("{name}")
@Produces(APPLICATION_JSON_WITH_CHARSET)
@RolesAllowed({"admin", "$owner=$graph $action=vertex_label_read"})
public String get(@Context GraphManager manager,
@PathParam("graph") String graph,
@PathParam("name") String name) {
@ -162,8 +133,6 @@ public class VertexLabelAPI extends API {
@Status(Status.ACCEPTED)
@Consumes(APPLICATION_JSON)
@Produces(APPLICATION_JSON_WITH_CHARSET)
@RolesAllowed({"admin", "$owner=$graph $action=vertex_label_delete"})
@RedirectFilter.RedirectMasterRole
public Map<String, Id> delete(@Context GraphManager manager,
@PathParam("graph") String graph,
@PathParam("name") String name) {
@ -179,7 +148,6 @@ public class VertexLabelAPI extends API {
/**
* JsonVertexLabel is only used to receive create and append requests
*/
@JsonIgnoreProperties(value = {"index_labels", "status"})
private static class JsonVertexLabel implements Checkable {
@JsonProperty("id")
@ -194,14 +162,10 @@ public class VertexLabelAPI extends API {
public String[] primaryKeys;
@JsonProperty("nullable_keys")
public String[] nullableKeys;
@JsonProperty("ttl")
public long ttl;
@JsonProperty("ttl_start_time")
public String ttlStartTime;
@JsonProperty("enable_label_index")
public Boolean enableLabelIndex;
@JsonProperty("user_data")
public Userdata userdata;
public Map<String, Object> userdata;
@JsonProperty("check_exist")
public Boolean checkExist;
@ -213,16 +177,6 @@ public class VertexLabelAPI extends API {
private VertexLabel.Builder convert2Builder(HugeGraph g) {
VertexLabel.Builder builder = g.schema().vertexLabel(this.name);
if (this.id != 0) {
E.checkArgument(this.id > 0,
"Only positive number can be assign as " +
"vertex label id");
E.checkArgument(g.mode() == GraphMode.RESTORING,
"Only accept vertex label id when graph in " +
"RESTORING mode, but '%s' is in mode '%s'",
g, g.mode());
builder.id(this.id);
}
if (this.idStrategy != null) {
builder.idStrategy(this.idStrategy);
}
@ -244,26 +198,16 @@ public class VertexLabelAPI extends API {
if (this.checkExist != null) {
builder.checkExist(this.checkExist);
}
if (this.ttl != 0) {
builder.ttl(this.ttl);
}
if (this.ttlStartTime != null) {
E.checkArgument(this.ttl > 0,
"Only set ttlStartTime when ttl is " +
"positive, but got ttl: %s", this.ttl);
builder.ttlStartTime(this.ttlStartTime);
}
return builder;
}
@Override
public String toString() {
return String.format("JsonVertexLabel{" +
"name=%s, idStrategy=%s, primaryKeys=%s, nullableKeys=%s, " +
"properties=%s, ttl=%s, ttlStartTime=%s}",
this.name, this.idStrategy, Arrays.toString(this.primaryKeys),
Arrays.toString(this.nullableKeys),
Arrays.toString(this.properties), this.ttl, this.ttlStartTime);
"name=%s, idStrategy=%s, primaryKeys=%s, " +
"nullableKeys=%s, properties=%s}",
this.name, this.idStrategy, this.primaryKeys,
this.nullableKeys, this.properties);
}
}
}

View File

@ -0,0 +1,85 @@
/*
* Copyright 2017 HugeGraph Authors
*
* 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.
*/
package com.baidu.hugegraph.api.traversers;
import java.util.Set;
import javax.inject.Singleton;
import javax.ws.rs.DefaultValue;
import javax.ws.rs.GET;
import javax.ws.rs.Path;
import javax.ws.rs.PathParam;
import javax.ws.rs.Produces;
import javax.ws.rs.QueryParam;
import javax.ws.rs.core.Context;
import org.slf4j.Logger;
import com.baidu.hugegraph.HugeGraph;
import com.baidu.hugegraph.api.API;
import com.baidu.hugegraph.api.graph.EdgeAPI;
import com.baidu.hugegraph.api.graph.VertexAPI;
import com.baidu.hugegraph.backend.id.Id;
import com.baidu.hugegraph.core.GraphManager;
import com.baidu.hugegraph.server.RestServer;
import com.baidu.hugegraph.traversal.optimize.HugeTraverser;
import com.baidu.hugegraph.type.define.Directions;
import com.baidu.hugegraph.util.Log;
import com.codahale.metrics.annotation.Timed;
@Path("graphs/{graph}/traversers/crosspoints")
@Singleton
public class CrosspointsAPI extends API {
private static final Logger LOG = Log.logger(RestServer.class);
@GET
@Timed
@Produces(APPLICATION_JSON_WITH_CHARSET)
public String get(@Context GraphManager manager,
@PathParam("graph") String graph,
@QueryParam("source") String source,
@QueryParam("target") String target,
@QueryParam("direction") String direction,
@QueryParam("label") String edgeLabel,
@QueryParam("max_depth") int maxDepth,
@QueryParam("degree") @DefaultValue("-1") long degree,
@QueryParam("capacity") @DefaultValue("-1") long capacity,
@QueryParam("limit") @DefaultValue("10") long limit) {
LOG.debug("Graph [{}] get crosspoints with paths from '{}', to '{}' " +
"with direction '{}', edge label '{}', max depth '{}', " +
"degree '{}', capacity '{}' and limit '{}'",
graph, source, target, direction, edgeLabel,
maxDepth, degree, capacity, limit);
Id sourceId = VertexAPI.checkAndParseVertexId(source);
Id targetId = VertexAPI.checkAndParseVertexId(target);
Directions dir = Directions.convert(EdgeAPI.parseDirection(direction));
HugeGraph g = graph(manager, graph);
HugeTraverser traverser = new HugeTraverser(g);
Set<HugeTraverser.Path> paths = traverser.paths(sourceId, dir,
targetId, dir,
edgeLabel, maxDepth,
degree, capacity,
limit);
return manager.serializer(g).writePaths("crosspoints", paths, true);
}
}

View File

@ -0,0 +1,116 @@
/*
* Copyright 2017 HugeGraph Authors
*
* 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.
*/
package com.baidu.hugegraph.api.traversers;
import java.util.Iterator;
import java.util.List;
import javax.inject.Singleton;
import javax.ws.rs.GET;
import javax.ws.rs.Path;
import javax.ws.rs.PathParam;
import javax.ws.rs.Produces;
import javax.ws.rs.QueryParam;
import javax.ws.rs.core.Context;
import org.apache.tinkerpop.gremlin.structure.Edge;
import org.slf4j.Logger;
import com.baidu.hugegraph.HugeGraph;
import com.baidu.hugegraph.api.API;
import com.baidu.hugegraph.api.filter.CompressInterceptor.Compress;
import com.baidu.hugegraph.backend.id.Id;
import com.baidu.hugegraph.backend.query.ConditionQuery;
import com.baidu.hugegraph.backend.store.Shard;
import com.baidu.hugegraph.core.GraphManager;
import com.baidu.hugegraph.server.RestServer;
import com.baidu.hugegraph.structure.HugeEdge;
import com.baidu.hugegraph.type.HugeType;
import com.baidu.hugegraph.util.E;
import com.baidu.hugegraph.util.Log;
import com.codahale.metrics.annotation.Timed;
@Path("graphs/{graph}/traversers/edges")
@Singleton
public class EdgesAPI extends API {
private static final Logger LOG = Log.logger(RestServer.class);
@GET
@Timed
@Compress
@Produces(APPLICATION_JSON_WITH_CHARSET)
public String list(@Context GraphManager manager,
@PathParam("graph") String graph,
@QueryParam("ids") List<String> stringIds) {
LOG.debug("Graph [{}] get edges by ids: {}", graph, stringIds);
E.checkArgument(stringIds != null && !stringIds.isEmpty(),
"Ids can't be null or empty");
Object[] ids = new Id[stringIds.size()];
for (int i = 0; i < ids.length; i++) {
ids[i] = HugeEdge.getIdValue(stringIds.get(i));
}
HugeGraph g = graph(manager, graph);
Iterator<Edge> edges = g.edges(ids);
return manager.serializer(g).writeEdges(edges, false);
}
@GET
@Timed
@Path("shards")
@Compress
@Produces(APPLICATION_JSON_WITH_CHARSET)
public String shards(@Context GraphManager manager,
@PathParam("graph") String graph,
@QueryParam("split_size") long splitSize) {
LOG.debug("Graph [{}] get vertex shards with split size '{}'",
graph, splitSize);
HugeGraph g = graph(manager, graph);
List<Shard> shards = g.graphTransaction()
.metadata(HugeType.EDGE_OUT, "splits", splitSize);
return manager.serializer(g).writeShards(shards);
}
@GET
@Timed
@Path("scan")
@Compress
@Produces(APPLICATION_JSON_WITH_CHARSET)
public String scan(@Context GraphManager manager,
@PathParam("graph") String graph,
@QueryParam("start") String start,
@QueryParam("end") String end) {
LOG.debug("Graph [{}] query edges by shard(start: {}, end: {}) ",
graph, start, end);
HugeGraph g = graph(manager, graph);
ConditionQuery query = new ConditionQuery(HugeType.EDGE_OUT);
query.scan(start, end);
Iterator<Edge> edges = g.edges(query);
return manager.serializer(g).writeEdges(edges, false);
}
}

View File

@ -0,0 +1,80 @@
/*
* Copyright 2017 HugeGraph Authors
*
* 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.
*/
package com.baidu.hugegraph.api.traversers;
import java.util.Set;
import javax.inject.Singleton;
import javax.ws.rs.DefaultValue;
import javax.ws.rs.GET;
import javax.ws.rs.Path;
import javax.ws.rs.PathParam;
import javax.ws.rs.Produces;
import javax.ws.rs.QueryParam;
import javax.ws.rs.core.Context;
import org.slf4j.Logger;
import com.baidu.hugegraph.HugeGraph;
import com.baidu.hugegraph.api.API;
import com.baidu.hugegraph.api.graph.EdgeAPI;
import com.baidu.hugegraph.api.graph.VertexAPI;
import com.baidu.hugegraph.backend.id.Id;
import com.baidu.hugegraph.core.GraphManager;
import com.baidu.hugegraph.server.RestServer;
import com.baidu.hugegraph.traversal.optimize.HugeTraverser;
import com.baidu.hugegraph.type.define.Directions;
import com.baidu.hugegraph.util.Log;
import com.codahale.metrics.annotation.Timed;
@Path("graphs/{graph}/traversers/kneighbor")
@Singleton
public class KneighborAPI extends API {
private static final Logger LOG = Log.logger(RestServer.class);
@GET
@Timed
@Produces(APPLICATION_JSON_WITH_CHARSET)
public String get(@Context GraphManager manager,
@PathParam("graph") String graph,
@QueryParam("source") String sourceV,
@QueryParam("direction") String direction,
@QueryParam("label") String edgeLabel,
@QueryParam("depth") int depth,
@QueryParam("degree") @DefaultValue("-1") long degree,
@QueryParam("limit") @DefaultValue("-1") long limit) {
LOG.debug("Graph [{}] get k-neighbor from '{}' with " +
"direction '{}', edge label '{}', depth '{}', " +
"degree '{}' and limit '{}'",
graph, sourceV, direction, edgeLabel, depth,
degree, limit);
Id source = VertexAPI.checkAndParseVertexId(sourceV);
Directions dir = Directions.convert(EdgeAPI.parseDirection(direction));
HugeGraph g = graph(manager, graph);
HugeTraverser traverser = new HugeTraverser(g);
Set<Id> ids = traverser.kneighbor(source, dir, edgeLabel, depth,
degree, limit);
return manager.serializer(g).writeIds("vertices", ids);
}
}

View File

@ -0,0 +1,83 @@
/*
* Copyright 2017 HugeGraph Authors
*
* 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.
*/
package com.baidu.hugegraph.api.traversers;
import java.util.Set;
import javax.inject.Singleton;
import javax.ws.rs.DefaultValue;
import javax.ws.rs.GET;
import javax.ws.rs.Path;
import javax.ws.rs.PathParam;
import javax.ws.rs.Produces;
import javax.ws.rs.QueryParam;
import javax.ws.rs.core.Context;
import org.slf4j.Logger;
import com.baidu.hugegraph.HugeGraph;
import com.baidu.hugegraph.api.API;
import com.baidu.hugegraph.api.graph.EdgeAPI;
import com.baidu.hugegraph.api.graph.VertexAPI;
import com.baidu.hugegraph.backend.id.Id;
import com.baidu.hugegraph.core.GraphManager;
import com.baidu.hugegraph.server.RestServer;
import com.baidu.hugegraph.traversal.optimize.HugeTraverser;
import com.baidu.hugegraph.type.define.Directions;
import com.baidu.hugegraph.util.Log;
import com.codahale.metrics.annotation.Timed;
@Path("graphs/{graph}/traversers/kout")
@Singleton
public class KoutAPI extends API {
private static final Logger LOG = Log.logger(RestServer.class);
@GET
@Timed
@Produces(APPLICATION_JSON_WITH_CHARSET)
public String get(@Context GraphManager manager,
@PathParam("graph") String graph,
@QueryParam("source") String source,
@QueryParam("direction") String direction,
@QueryParam("label") String edgeLabel,
@QueryParam("depth") int depth,
@QueryParam("nearest")
@DefaultValue("true") boolean nearest,
@QueryParam("degree") @DefaultValue("-1") long degree,
@QueryParam("capacity") @DefaultValue("-1") long capacity,
@QueryParam("limit") @DefaultValue("-1") long limit) {
LOG.debug("Graph [{}] get k-out from '{}' with " +
"direction '{}', edge label '{}', depth '{}', nearest '{}'," +
" degree '{}', capacity '{}' and limit '{}'",
graph, source, direction, edgeLabel, depth, nearest,
degree, capacity, limit);
Id sourceId = VertexAPI.checkAndParseVertexId(source);
Directions dir = Directions.convert(EdgeAPI.parseDirection(direction));
HugeGraph g = graph(manager, graph);
HugeTraverser traverser = new HugeTraverser(g);
Set<Id> ids = traverser.kout(sourceId, dir, edgeLabel, depth,
nearest, degree, capacity, limit);
return manager.serializer(g).writeIds("vertices", ids);
}
}

View File

@ -0,0 +1,83 @@
/*
* Copyright 2017 HugeGraph Authors
*
* 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.
*/
package com.baidu.hugegraph.api.traversers;
import java.util.Set;
import javax.inject.Singleton;
import javax.ws.rs.DefaultValue;
import javax.ws.rs.GET;
import javax.ws.rs.Path;
import javax.ws.rs.PathParam;
import javax.ws.rs.Produces;
import javax.ws.rs.QueryParam;
import javax.ws.rs.core.Context;
import org.slf4j.Logger;
import com.baidu.hugegraph.HugeGraph;
import com.baidu.hugegraph.api.API;
import com.baidu.hugegraph.api.graph.EdgeAPI;
import com.baidu.hugegraph.api.graph.VertexAPI;
import com.baidu.hugegraph.backend.id.Id;
import com.baidu.hugegraph.core.GraphManager;
import com.baidu.hugegraph.server.RestServer;
import com.baidu.hugegraph.traversal.optimize.HugeTraverser;
import com.baidu.hugegraph.type.define.Directions;
import com.baidu.hugegraph.util.Log;
import com.codahale.metrics.annotation.Timed;
@Path("graphs/{graph}/traversers/paths")
@Singleton
public class PathsAPI extends API {
private static final Logger LOG = Log.logger(RestServer.class);
@GET
@Timed
@Produces(APPLICATION_JSON_WITH_CHARSET)
public String get(@Context GraphManager manager,
@PathParam("graph") String graph,
@QueryParam("source") String source,
@QueryParam("target") String target,
@QueryParam("direction") String direction,
@QueryParam("label") String edgeLabel,
@QueryParam("max_depth") int maxDepth,
@QueryParam("degree") @DefaultValue("-1") long degree,
@QueryParam("capacity") @DefaultValue("-1") long capacity,
@QueryParam("limit") @DefaultValue("10") long limit) {
LOG.debug("Graph [{}] get paths from '{}', to '{}' with " +
"direction {}, edge label {}, max depth '{}', " +
"degree '{}', capacity '{}' and limit '{}'",
graph, source, target, direction, edgeLabel, maxDepth,
degree, capacity, limit);
Id sourceId = VertexAPI.checkAndParseVertexId(source);
Id targetId = VertexAPI.checkAndParseVertexId(target);
Directions dir = Directions.convert(EdgeAPI.parseDirection(direction));
HugeGraph g = graph(manager, graph);
HugeTraverser traverser = new HugeTraverser(g);
Set<HugeTraverser.Path> paths;
paths = traverser.paths(sourceId, dir, targetId, dir.opposite(),
edgeLabel, maxDepth, degree, capacity, limit);
return manager.serializer(g).writePaths("paths", paths, false);
}
}

View File

@ -0,0 +1,84 @@
/*
* Copyright 2017 HugeGraph Authors
*
* 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.
*/
package com.baidu.hugegraph.api.traversers;
import java.util.List;
import javax.inject.Singleton;
import javax.ws.rs.DefaultValue;
import javax.ws.rs.GET;
import javax.ws.rs.Path;
import javax.ws.rs.PathParam;
import javax.ws.rs.Produces;
import javax.ws.rs.QueryParam;
import javax.ws.rs.core.Context;
import org.slf4j.Logger;
import com.baidu.hugegraph.HugeGraph;
import com.baidu.hugegraph.api.API;
import com.baidu.hugegraph.api.graph.EdgeAPI;
import com.baidu.hugegraph.api.graph.VertexAPI;
import com.baidu.hugegraph.backend.id.Id;
import com.baidu.hugegraph.core.GraphManager;
import com.baidu.hugegraph.server.RestServer;
import com.baidu.hugegraph.traversal.optimize.HugeTraverser;
import com.baidu.hugegraph.type.define.Directions;
import com.baidu.hugegraph.util.Log;
import com.codahale.metrics.annotation.Timed;
@Path("graphs/{graph}/traversers/shortestpath")
@Singleton
public class ShortestPathAPI extends API {
private static final Logger LOG = Log.logger(RestServer.class);
@GET
@Timed
@Produces(APPLICATION_JSON_WITH_CHARSET)
public String get(@Context GraphManager manager,
@PathParam("graph") String graph,
@QueryParam("source") String source,
@QueryParam("target") String target,
@QueryParam("direction") String direction,
@QueryParam("label") String edgeLabel,
@QueryParam("max_depth") int maxDepth,
@QueryParam("degree") @DefaultValue("-1") long degree,
@QueryParam("capacity")
@DefaultValue("-1") long capacity) {
LOG.debug("Graph [{}] get shortest path from '{}', to '{}' with " +
"direction {}, edge label {}, max depth '{}', " +
"degree '{}' and capacity '{}'",
graph, source, target, direction, edgeLabel, maxDepth,
degree, capacity);
Id sourceId = VertexAPI.checkAndParseVertexId(source);
Id targetId = VertexAPI.checkAndParseVertexId(target);
Directions dir = Directions.convert(EdgeAPI.parseDirection(direction));
HugeGraph g = graph(manager, graph);
HugeTraverser traverser = new HugeTraverser(g);
List<Id> path = traverser.shortestPath(sourceId, targetId, dir,
edgeLabel, maxDepth,
degree, capacity);
return manager.serializer(g).writeIds("path", path);
}
}

View File

@ -1,59 +1,57 @@
/*
* Copyright 2017 HugeGraph Authors
*
* 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
* 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.
* 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.hugegraph.api.traversers;
import static org.apache.hugegraph.traversal.algorithm.HugeTraverser.DEFAULT_PAGE_LIMIT;
package com.baidu.hugegraph.api.traversers;
import java.util.Iterator;
import java.util.List;
import org.apache.hugegraph.HugeGraph;
import org.apache.hugegraph.api.API;
import org.apache.hugegraph.api.filter.CompressInterceptor.Compress;
import org.apache.hugegraph.api.graph.VertexAPI;
import org.apache.hugegraph.backend.id.Id;
import org.apache.hugegraph.backend.query.ConditionQuery;
import org.apache.hugegraph.backend.store.Shard;
import org.apache.hugegraph.core.GraphManager;
import org.apache.hugegraph.type.HugeType;
import org.apache.hugegraph.util.E;
import org.apache.hugegraph.util.Log;
import javax.inject.Singleton;
import javax.ws.rs.GET;
import javax.ws.rs.Path;
import javax.ws.rs.PathParam;
import javax.ws.rs.Produces;
import javax.ws.rs.QueryParam;
import javax.ws.rs.core.Context;
import org.apache.tinkerpop.gremlin.structure.Vertex;
import org.slf4j.Logger;
import com.baidu.hugegraph.HugeGraph;
import com.baidu.hugegraph.api.API;
import com.baidu.hugegraph.api.filter.CompressInterceptor.Compress;
import com.baidu.hugegraph.api.graph.VertexAPI;
import com.baidu.hugegraph.backend.id.Id;
import com.baidu.hugegraph.backend.query.ConditionQuery;
import com.baidu.hugegraph.backend.store.Shard;
import com.baidu.hugegraph.core.GraphManager;
import com.baidu.hugegraph.server.RestServer;
import com.baidu.hugegraph.type.HugeType;
import com.baidu.hugegraph.util.E;
import com.baidu.hugegraph.util.Log;
import com.codahale.metrics.annotation.Timed;
import io.swagger.v3.oas.annotations.tags.Tag;
import jakarta.inject.Singleton;
import jakarta.ws.rs.DefaultValue;
import jakarta.ws.rs.GET;
import jakarta.ws.rs.Path;
import jakarta.ws.rs.PathParam;
import jakarta.ws.rs.Produces;
import jakarta.ws.rs.QueryParam;
import jakarta.ws.rs.core.Context;
@Path("graphs/{graph}/traversers/vertices")
@Singleton
@Tag(name = "VerticesAPI")
public class VerticesAPI extends API {
private static final Logger LOG = Log.logger(VerticesAPI.class);
private static final Logger LOG = Log.logger(RestServer.class);
@GET
@Timed
@ -65,7 +63,7 @@ public class VerticesAPI extends API {
LOG.debug("Graph [{}] get vertices by ids: {}", graph, stringIds);
E.checkArgument(stringIds != null && !stringIds.isEmpty(),
"The ids parameter can't be null or empty");
"Ids can't be null or empty");
Object[] ids = new Id[stringIds.size()];
for (int i = 0; i < ids.length; i++) {
@ -90,8 +88,9 @@ public class VerticesAPI extends API {
graph, splitSize);
HugeGraph g = graph(manager, graph);
List<Shard> shards = g.metadata(HugeType.VERTEX, "splits", splitSize);
return manager.serializer(g).writeList("shards", shards);
List<Shard> shards = g.graphTransaction()
.metadata(HugeType.VERTEX, "splits", splitSize);
return manager.serializer(g).writeShards(shards);
}
@GET
@ -102,23 +101,16 @@ public class VerticesAPI extends API {
public String scan(@Context GraphManager manager,
@PathParam("graph") String graph,
@QueryParam("start") String start,
@QueryParam("end") String end,
@QueryParam("page") String page,
@QueryParam("page_limit")
@DefaultValue(DEFAULT_PAGE_LIMIT) long pageLimit) {
LOG.debug("Graph [{}] query vertices by shard(start: {}, end: {}, " +
"page: {}) ", graph, start, end, page);
@QueryParam("end") String end) {
LOG.debug("Graph [{}] query vertices by shard(start: {}, end: {}) ",
graph, start, end);
HugeGraph g = graph(manager, graph);
ConditionQuery query = new ConditionQuery(HugeType.VERTEX);
query.scan(start, end);
query.page(page);
if (query.paging()) {
query.limit(pageLimit);
}
Iterator<Vertex> vertices = g.vertices(query);
return manager.serializer(g).writeVertices(vertices, query.paging());
return manager.serializer(g).writeVertices(vertices, false);
}
}

View File

@ -1,53 +1,54 @@
/*
* Copyright 2017 HugeGraph Authors
*
* 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
* 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.
* 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.hugegraph.api.variables;
package com.baidu.hugegraph.api.variables;
import java.util.Map;
import java.util.Optional;
import org.apache.hugegraph.HugeGraph;
import org.apache.hugegraph.api.API;
import org.apache.hugegraph.core.GraphManager;
import org.apache.hugegraph.util.E;
import org.apache.hugegraph.util.Log;
import javax.inject.Singleton;
import javax.ws.rs.Consumes;
import javax.ws.rs.DELETE;
import javax.ws.rs.GET;
import javax.ws.rs.NotFoundException;
import javax.ws.rs.PUT;
import javax.ws.rs.Path;
import javax.ws.rs.PathParam;
import javax.ws.rs.Produces;
import javax.ws.rs.core.Context;
import org.slf4j.Logger;
import com.baidu.hugegraph.HugeGraph;
import com.baidu.hugegraph.api.API;
import com.baidu.hugegraph.core.GraphManager;
import com.baidu.hugegraph.server.RestServer;
import com.baidu.hugegraph.util.E;
import com.baidu.hugegraph.util.Log;
import com.codahale.metrics.annotation.Timed;
import com.google.common.collect.ImmutableMap;
import io.swagger.v3.oas.annotations.tags.Tag;
import jakarta.inject.Singleton;
import jakarta.ws.rs.Consumes;
import jakarta.ws.rs.DELETE;
import jakarta.ws.rs.GET;
import jakarta.ws.rs.NotFoundException;
import jakarta.ws.rs.PUT;
import jakarta.ws.rs.Path;
import jakarta.ws.rs.PathParam;
import jakarta.ws.rs.Produces;
import jakarta.ws.rs.core.Context;
@Path("graphs/{graph}/variables")
@Singleton
@Tag(name = "VariablesAPI")
public class VariablesAPI extends API {
private static final Logger LOG = Log.logger(VariablesAPI.class);
private static final Logger LOG = Log.logger(RestServer.class);
@PUT
@Timed
@ -91,7 +92,7 @@ public class VariablesAPI extends API {
Optional<?> object = g.variables().get(key);
if (!object.isPresent()) {
throw new NotFoundException(String.format(
"Variable '%s' does not exist", key));
"Variable '%s' does not exist", key));
}
return ImmutableMap.of(key, object.get());
}

View File

@ -0,0 +1,165 @@
/*
* Copyright 2017 HugeGraph Authors
*
* 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.
*/
package com.baidu.hugegraph.auth;
import java.io.IOException;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.ThreadFactory;
import org.apache.commons.lang3.SystemUtils;
import org.apache.tinkerpop.gremlin.process.traversal.dsl.graph.GraphTraversalSource;
import org.apache.tinkerpop.gremlin.server.GraphManager;
import org.apache.tinkerpop.gremlin.server.GremlinServer;
import org.apache.tinkerpop.gremlin.server.Settings;
import org.apache.tinkerpop.gremlin.server.util.MetricManager;
import org.apache.tinkerpop.gremlin.server.util.ServerGremlinExecutor;
import org.apache.tinkerpop.gremlin.server.util.ThreadFactoryUtil;
import org.apache.tinkerpop.gremlin.structure.Graph;
import org.slf4j.Logger;
import com.baidu.hugegraph.HugeException;
import com.baidu.hugegraph.HugeGraph;
import com.baidu.hugegraph.auth.HugeGraphAuthProxy.Context;
import com.baidu.hugegraph.auth.HugeGraphAuthProxy.ContextThreadPoolExecutor;
import com.baidu.hugegraph.util.Log;
import io.netty.channel.EventLoopGroup;
import io.netty.channel.epoll.EpollEventLoopGroup;
import io.netty.channel.nio.NioEventLoopGroup;
/**
* GremlinServer with custom ServerGremlinExecutor, which can pass Context
*/
public class ContextGremlinServer extends GremlinServer {
private static final Logger LOG = Log.logger(ContextGremlinServer.class);
@SuppressWarnings("deprecation")
public ContextGremlinServer(final Settings settings) {
/*
* TODO: use GremlinServer(Settings, ExecutorService)
* which can be obtained from https://github.com/apache/tinkerpop/pull/813
*
* NOTE: should call GremlinServer::configureMetrics() but it's private
* settings.optionalMetrics().ifPresent(GremlinServer::configureMetrics)
*/
super(create(settings));
settings.optionalMetrics().ifPresent(this::configureMetrics);
}
public void injectAuthGraph() {
HugeGraphAuthProxy.setContext(Context.admin());
GraphManager manager = this.getServerGremlinExecutor()
.getGraphManager();
for (String name : manager.getGraphNames()) {
Graph graph = manager.getGraph(name);
graph = new HugeGraphAuthProxy((HugeGraph) graph);
manager.putGraph(name, graph);
}
}
public void injectTraversalSource(String prefix) {
GraphManager manager = this.getServerGremlinExecutor()
.getGraphManager();
for (String graph : manager.getGraphNames()) {
GraphTraversalSource g = manager.getGraph(graph).traversal();
String gName = prefix + graph;
if (manager.getTraversalSource(gName) != null) {
throw new HugeException(
"Found existing name '%s' in global bindings, " +
"it may lead to gremlin query error.", gName);
}
// Add a traversal source for all graphs with customed rule.
manager.putTraversalSource(gName, g);
}
}
static ServerGremlinExecutor<EventLoopGroup> create(Settings settings) {
if (settings.gremlinPool == 0) {
settings.gremlinPool = Runtime.getRuntime().availableProcessors();
}
ExecutorService service = newGremlinExecutorService(settings);
EventLoopGroup group;
boolean isEpollEnabled = settings.useEpollEventLoop &&
SystemUtils.IS_OS_LINUX;
ThreadFactory factory = ThreadFactoryUtil.create("worker-%d");
if (isEpollEnabled) {
group = new EpollEventLoopGroup(settings.threadPoolWorker, factory);
} else {
group = new NioEventLoopGroup(settings.threadPoolWorker, factory);
}
return new ServerGremlinExecutor<>(settings, service,
group, EventLoopGroup.class);
}
static ExecutorService newGremlinExecutorService(Settings settings) {
int size = settings.gremlinPool;
ThreadFactory factory = ThreadFactoryUtil.create("exec-%d");
return new ContextThreadPoolExecutor(size, size, factory);
}
private void configureMetrics(final Settings.ServerMetrics settings) {
final MetricManager metrics = MetricManager.INSTANCE;
// The following codes are copied from GremlinServer
settings.optionalConsoleReporter().ifPresent(config -> {
if (config.enabled) {
metrics.addConsoleReporter(config.interval);
}
});
settings.optionalCsvReporter().ifPresent(config -> {
if (config.enabled) {
metrics.addCsvReporter(config.interval, config.fileName);
}
});
settings.optionalJmxReporter().ifPresent(config -> {
if (config.enabled) {
metrics.addJmxReporter(config.domain, config.agentId);
}
});
settings.optionalSlf4jReporter().ifPresent(config -> {
if (config.enabled) {
metrics.addSlf4jReporter(config.interval, config.loggerName);
}
});
settings.optionalGangliaReporter().ifPresent(config -> {
if (config.enabled) {
try {
metrics.addGangliaReporter(config.host, config.port,
config.optionalAddressingMode(),
config.ttl, config.protocol31,
config.hostUUID, config.spoof,
config.interval);
} catch (IOException ioe) {
LOG.warn("Error configuring the Ganglia Reporter.", ioe);
}
}
});
settings.optionalGraphiteReporter().ifPresent(config -> {
if (config.enabled) {
metrics.addGraphiteReporter(config.host, config.port,
config.prefix, config.interval);
}
});
}
}

View File

@ -0,0 +1,38 @@
/*
* Copyright 2017 HugeGraph Authors
*
* 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.
*/
package com.baidu.hugegraph.auth;
import org.apache.commons.configuration.Configuration;
import org.apache.tinkerpop.gremlin.structure.Graph;
import com.baidu.hugegraph.HugeFactory;
import com.baidu.hugegraph.auth.HugeGraphAuthProxy.Context;
public class HugeFactoryAuthProxy {
static {
HugeGraphAuthProxy.setContext(Context.admin());
}
public static Graph open(Configuration config) {
// Inject authentication (replace HugeGraph with HugeGraphAuthProxy)
return new HugeGraphAuthProxy(HugeFactory.open(config));
}
}

View File

@ -0,0 +1,296 @@
/*
* Copyright 2017 HugeGraph Authors
*
* 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.
*/
package com.baidu.hugegraph.auth;
import java.util.Iterator;
import java.util.concurrent.LinkedBlockingQueue;
import java.util.concurrent.ThreadFactory;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;
import javax.ws.rs.ForbiddenException;
import org.apache.tinkerpop.gremlin.process.computer.GraphComputer;
import org.apache.tinkerpop.gremlin.process.traversal.dsl.graph.GraphTraversalSource;
import org.apache.tinkerpop.gremlin.structure.Edge;
import org.apache.tinkerpop.gremlin.structure.Graph;
import org.apache.tinkerpop.gremlin.structure.Transaction;
import org.apache.tinkerpop.gremlin.structure.Vertex;
import org.apache.tinkerpop.gremlin.structure.io.Io;
import org.slf4j.Logger;
import com.baidu.hugegraph.HugeException;
import com.baidu.hugegraph.HugeGraph;
import com.baidu.hugegraph.config.HugeConfig;
import com.baidu.hugegraph.exception.NotSupportException;
import com.baidu.hugegraph.schema.SchemaManager;
import com.baidu.hugegraph.structure.HugeFeatures;
import com.baidu.hugegraph.task.HugeTaskScheduler;
import com.baidu.hugegraph.util.E;
import com.baidu.hugegraph.util.Log;
public class HugeGraphAuthProxy implements Graph {
private static final Logger LOG = Log.logger(HugeGraph.class);
private static final String ROLE_ADMIN = StandardAuthenticator.ROLE_ADMIN;
private final HugeGraph hugegraph;
public HugeGraphAuthProxy(HugeGraph hugegraph) {
LOG.info("Wrap graph '{}' with HugeGraphAuthProxy", hugegraph.name());
this.hugegraph = hugegraph;
}
@Override
public Vertex addVertex(Object... keyValues) {
this.verifyPermission();
return this.hugegraph.addVertex(keyValues);
}
@Override
public <C extends GraphComputer> C compute(Class<C> clazz)
throws IllegalArgumentException {
this.verifyPermission();
return this.hugegraph.compute(clazz);
}
@Override
public GraphComputer compute() throws IllegalArgumentException {
this.verifyPermission();
return this.hugegraph.compute();
}
@Override
public GraphTraversalSource traversal() {
this.verifyPermission();
return new GraphTraversalSourceProxy(this.hugegraph);
}
@SuppressWarnings("rawtypes")
@Override
public <I extends Io> I io(final Io.Builder<I> builder) {
this.verifyPermission();
return this.hugegraph.io(builder);
}
@Override
public Iterator<Vertex> vertices(Object... objects) {
this.verifyPermission();
return this.hugegraph.vertices(objects);
}
@Override
public Iterator<Edge> edges(Object... objects) {
this.verifyPermission();
return this.hugegraph.edges(objects);
}
@Override
public Transaction tx() {
// Can't verifyPermission() here, will be called by rollbackAll()
return this.hugegraph.tx();
}
@Override
public void close() throws HugeException {
this.verifyPermission("admin");
this.hugegraph.close();
}
@Override
public HugeFeatures features() {
// Can't verifyPermission() here, will be called by rollbackAll()
return this.hugegraph.features();
}
@Override
public Variables variables() {
this.verifyPermission();
return this.hugegraph.variables();
}
@Override
public HugeConfig configuration() {
throw new NotSupportException("Graph.configuration()");
}
@Override
public String toString() {
this.verifyPermission();
return this.hugegraph.toString();
}
public HugeGraph graph() {
this.verifyPermission();
return this.hugegraph;
}
public HugeGraph hugegraph() {
this.verifyPermission(ROLE_ADMIN);
return this.hugegraph;
}
public SchemaManager schema() {
this.verifyPermission();
return this.hugegraph.schema();
}
public String backend() {
this.verifyPermission();
return this.hugegraph.backend();
}
public void initBackend() {
this.verifyPermission(ROLE_ADMIN);
this.hugegraph.initBackend();
}
public void clearBackend() {
this.verifyPermission(ROLE_ADMIN);
this.hugegraph.clearBackend();
}
public void restoring(boolean restoring) {
this.verifyPermission(ROLE_ADMIN);
this.hugegraph.restoring(restoring);
}
public boolean restoring() {
this.verifyPermission(ROLE_ADMIN);
return this.hugegraph.restoring();
}
public HugeTaskScheduler taskScheduler() {
this.verifyPermission();
return this.hugegraph.taskScheduler();
}
private void verifyPermission() {
/*
* The owner role should match the graph name
* NOTE: the graph names in gremlin-server.yaml/graphs and
* hugegraph.properties/store must be the same if enable auth.
*/
this.verifyPermission(this.hugegraph.name());
}
private void verifyPermission(String permission) {
Context context = getContext();
E.checkState(context != null,
"Missing authentication context " +
"when accessing a Graph with permission control");
String role = context.role();
if (!role.equals(ROLE_ADMIN) && !role.equals(permission)) {
throw new ForbiddenException("Permission denied");
}
}
private class GraphTraversalSourceProxy extends GraphTraversalSource {
public GraphTraversalSourceProxy(Graph graph) {
super(graph);
}
@Override
public Graph getGraph() {
verifyPermission();
return this.graph;
}
}
private static final ThreadLocal<Context> contexts = new ThreadLocal<>();
public static void setContext(Context context) {
contexts.set(context);
}
public static Context getContext() {
return contexts.get();
}
public static void resetContext() {
contexts.remove();
}
public static class Context {
private final String username;
private final String role;
public Context(String username, String role) {
this.username = username;
this.role = role;
}
public String username() {
return this.username;
}
public String role() {
return this.role;
}
private static final Context ADMIN;
static {
ADMIN = new Context("admin", ROLE_ADMIN);
}
public static Context admin() {
return ADMIN;
}
}
public static class ContextThreadPoolExecutor extends ThreadPoolExecutor {
public ContextThreadPoolExecutor(int corePoolSize, int maxPoolSize,
ThreadFactory threadFactory) {
super(corePoolSize, maxPoolSize, 0L, TimeUnit.MILLISECONDS,
new LinkedBlockingQueue<Runnable>(), threadFactory);
}
@Override
public void execute(Runnable command) {
super.execute(new ContextTask(command));
}
}
public static class ContextTask implements Runnable {
private final Runnable runner;
private final Context context;
public ContextTask(Runnable runner) {
this.context = HugeGraphAuthProxy.getContext();
this.runner = runner;
}
@Override
public void run() {
HugeGraphAuthProxy.setContext(this.context);
try {
this.runner.run();
} finally {
HugeGraphAuthProxy.resetContext();
}
}
}
}

View File

@ -0,0 +1,138 @@
/*
* Copyright 2017 HugeGraph Authors
*
* 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.
*/
package com.baidu.hugegraph.auth;
import static org.apache.tinkerpop.gremlin.groovy.jsr223.dsl.credential.CredentialGraphTokens.PROPERTY_PASSWORD;
import static org.apache.tinkerpop.gremlin.groovy.jsr223.dsl.credential.CredentialGraphTokens.PROPERTY_USERNAME;
import java.util.HashMap;
import java.util.Map;
import org.apache.tinkerpop.gremlin.server.auth.AuthenticatedUser;
import org.apache.tinkerpop.gremlin.server.auth.AuthenticationException;
import org.apache.tinkerpop.gremlin.server.auth.SimpleAuthenticator;
import com.baidu.hugegraph.auth.HugeGraphAuthProxy.Context;
import com.baidu.hugegraph.config.HugeConfig;
import com.baidu.hugegraph.config.OptionSpace;
import com.baidu.hugegraph.config.ServerOptions;
import com.baidu.hugegraph.util.E;
public class StandardAuthenticator extends SimpleAuthenticator {
public static final String ROLE_NONE = "";
public static final String ROLE_ADMIN = "admin";
public static final String ROLE_USER = "user";
public static final String ROLE_OWNER = "$owner";
public static final String ROLE_DYNAMIC = "$dynamic";
public static final String USER_ADMIN = ROLE_ADMIN;
public static final String USER_ANONYMOUS =
AuthenticatedUser.ANONYMOUS_USERNAME;
private boolean requireAuth;
private final Map<String, String> tokens;
public StandardAuthenticator(HugeConfig config) {
this();
this.load(config);
}
public StandardAuthenticator() {
this.requireAuth = true;
this.tokens = new HashMap<>();
}
@Override
public void setup(final Map<String, Object> config) {
E.checkState(config != null,
"Must provide a 'config' in the 'authentication'");
String path = (String) config.get("tokens");
E.checkState(path != null,
"Credentials configuration missing key 'tokens'");
OptionSpace.register("tokens", ServerOptions.instance());
this.load(new HugeConfig(path));
}
@Override
public boolean requireAuthentication() {
return this.requireAuth;
}
/**
* This authentication method is for Gremlin Server
*/
@Override
public AuthenticatedUser authenticate(final Map<String, String> credentials)
throws AuthenticationException {
String username = credentials.get(PROPERTY_USERNAME);
String password = credentials.get(PROPERTY_PASSWORD);
// Currently we just use config tokens to authenticate
String role = this.authenticate(username, password);
if (!verifyRole(role)) {
throw new AuthenticationException("Invalid username or password");
}
return new AuthenticatedUser(username);
}
/**
* Verify if a user is legal
* @param username
* @param password
* @return String No permission if return ROLE_NONE else return a role
*/
public String authenticate(final String username, final String password) {
E.checkArgumentNotNull(username, "The username can't be null");
E.checkArgumentNotNull(password, "The password can't be null");
String role;
if (password.equals(this.tokens.get(username))) {
// Return user name as role
role = username;
} else {
role = ROLE_NONE;
}
/*
* Set authentication context
* TODO: unset context after finishing a request,
* now must set context to update last context even if not authorized.
*/
HugeGraphAuthProxy.setContext(new Context(username, role));
return role;
}
private void load(HugeConfig config) {
this.requireAuth = config.get(ServerOptions.REQUIRE_AUTH);
this.tokens.put(USER_ADMIN, config.get(ServerOptions.ADMIN_TOKEN));
this.tokens.putAll(config.getMap(ServerOptions.USER_TOKENS));
}
public static final boolean verifyRole(String role) {
if (role == ROLE_NONE || role == null || role.isEmpty()) {
return false;
} else {
return true;
}
}
}

View File

@ -0,0 +1,132 @@
/*
* Copyright 2017 HugeGraph Authors
*
* 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.
*/
package com.baidu.hugegraph.config;
import static com.baidu.hugegraph.config.OptionChecker.disallowEmpty;
import static com.baidu.hugegraph.config.OptionChecker.nonNegativeInt;
import static com.baidu.hugegraph.config.OptionChecker.positiveInt;
import static com.baidu.hugegraph.config.OptionChecker.rangeInt;
public class ServerOptions extends OptionHolder {
private ServerOptions() {
super();
}
private static volatile ServerOptions instance;
public static synchronized ServerOptions instance() {
if (instance == null) {
instance = new ServerOptions();
instance.registerOptions();
}
return instance;
}
public static final ConfigOption<String> REST_SERVER_URL =
new ConfigOption<>(
"restserver.url",
"The url for listening of hugeserver.",
disallowEmpty(),
"http://127.0.0.1:8080"
);
public static final ConfigOption<String> GREMLIN_SERVER_URL =
new ConfigOption<>(
"gremlinserver.url",
"The url of gremlin server.",
disallowEmpty(),
"http://127.0.0.1:8182"
);
public static final ConfigListOption<String> GRAPHS =
new ConfigListOption<>(
"graphs",
"The map of graphs' name and config file.",
disallowEmpty(),
"hugegraph:conf/hugegraph.properties"
);
public static final ConfigOption<Integer> MAX_VERTICES_PER_BATCH =
new ConfigOption<>(
"batch.max_vertices_per_batch",
"The maximum number of vertices submitted per batch.",
positiveInt(),
500
);
public static final ConfigOption<Integer> MAX_EDGES_PER_BATCH =
new ConfigOption<>(
"batch.max_edges_per_batch",
"The maximum number of edges submitted per batch.",
positiveInt(),
500
);
public static final ConfigOption<Integer> MAX_WRITE_RATIO =
new ConfigOption<>(
"batch.max_write_ratio",
"The maximum thread ratio for batch writing, " +
"only take effect if the batch.max_write_threads is 0.",
rangeInt(0, 100),
50
);
public static final ConfigOption<Integer> MAX_WRITE_THREADS =
new ConfigOption<>(
"batch.max_write_threads",
"The maximum threads for batch writing, " +
"if the value is 0, the actual value will be set to " +
"batch.max_write_ratio * total-rest-threads.",
nonNegativeInt(),
0);
public static final ConfigOption<Boolean> ALLOW_TRACE =
new ConfigOption<>(
"exception.allow_trace",
"Whether to allow exception trace stack.",
disallowEmpty(),
false
);
public static final ConfigOption<Boolean> REQUIRE_AUTH =
new ConfigOption<>(
"auth.require_authentication",
"Whether to enable authentication.",
disallowEmpty(),
false
);
public static final ConfigOption<String> ADMIN_TOKEN =
new ConfigOption<>(
"auth.admin_token",
"Token for administrator operations.",
disallowEmpty(),
"162f7848-0b6d-4faf-b557-3a0797869c55"
);
public static final ConfigListOption<String> USER_TOKENS =
new ConfigListOption<>(
"auth.user_tokens",
"The map of user tokens with name and password.",
disallowEmpty(),
"hugegraph:9fd95c9c-711b-415b-b85f-d4df46ba5c31"
);
}

View File

@ -0,0 +1,236 @@
/*
* Copyright 2017 HugeGraph Authors
*
* 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.
*/
package com.baidu.hugegraph.core;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicInteger;
import org.apache.tinkerpop.gremlin.server.util.MetricManager;
import org.apache.tinkerpop.gremlin.structure.Graph;
import org.apache.tinkerpop.gremlin.structure.Transaction;
import org.apache.tinkerpop.gremlin.structure.io.IoCore;
import org.apache.tinkerpop.gremlin.structure.util.GraphFactory;
import org.slf4j.Logger;
import com.baidu.hugegraph.HugeGraph;
import com.baidu.hugegraph.auth.HugeGraphAuthProxy;
import com.baidu.hugegraph.auth.StandardAuthenticator;
import com.baidu.hugegraph.backend.cache.Cache;
import com.baidu.hugegraph.backend.cache.CacheManager;
import com.baidu.hugegraph.backend.store.BackendStoreInfo;
import com.baidu.hugegraph.backend.store.memory.InMemoryDBStoreProvider;
import com.baidu.hugegraph.config.HugeConfig;
import com.baidu.hugegraph.config.ServerOptions;
import com.baidu.hugegraph.exception.NotSupportException;
import com.baidu.hugegraph.metric.MetricsUtil;
import com.baidu.hugegraph.metric.ServerReporter;
import com.baidu.hugegraph.serializer.JsonSerializer;
import com.baidu.hugegraph.serializer.Serializer;
import com.baidu.hugegraph.server.RestServer;
import com.baidu.hugegraph.util.Log;
import com.codahale.metrics.MetricRegistry;
public final class GraphManager {
private static final Logger LOG = Log.logger(RestServer.class);
private final Map<String, Graph> graphs;
private final StandardAuthenticator authenticator;
public GraphManager(HugeConfig conf) {
this.graphs = new ConcurrentHashMap<>();
this.authenticator = new StandardAuthenticator(conf);
this.loadGraphs(conf.getMap(ServerOptions.GRAPHS));
this.checkBackendVersionOrExit();
this.addMetrics(conf);
}
public void loadGraphs(final Map<String, String> graphConfs) {
graphConfs.entrySet().forEach(conf -> {
try {
final Graph newGraph = GraphFactory.open(conf.getValue());
this.graphs.put(conf.getKey(), newGraph);
LOG.info("Graph '{}' was successfully configured via '{}'",
conf.getKey(), conf.getValue());
} catch (RuntimeException e) {
LOG.error("Graph '{}': '{}' can't be instantiated",
conf.getKey(), conf.getValue(), e);
}
});
}
public Map<String, Graph> graphs() {
return this.graphs;
}
public HugeGraph graph(String name) {
Graph graph = this.graphs.get(name);
if (graph == null) {
return null;
} else if (graph instanceof HugeGraphAuthProxy) {
return ((HugeGraphAuthProxy) graph).graph();
} else if (graph instanceof HugeGraph) {
return (HugeGraph) graph;
}
throw new NotSupportException("graph instance of %s", graph.getClass());
}
public Serializer serializer(Graph g) {
// TODO: cache Serializer
return new JsonSerializer(g.io(IoCore.graphson()).writer()
.wrapAdjacencyList(true).create());
}
public void rollbackAll() {
this.graphs.entrySet().forEach(e -> {
final Graph graph = e.getValue();
if (graph.features().graph().supportsTransactions() &&
graph.tx().isOpen()) {
graph.tx().rollback();
}
});
}
public void rollback(final Set<String> graphSourceNamesToCloseTxOn) {
closeTx(graphSourceNamesToCloseTxOn, Transaction.Status.ROLLBACK);
}
public void commitAll() {
this.graphs.entrySet().forEach(e -> {
final Graph graph = e.getValue();
if (graph.features().graph().supportsTransactions() &&
graph.tx().isOpen()) {
graph.tx().commit();
}
});
}
public void commit(final Set<String> graphSourceNamesToCloseTxOn) {
closeTx(graphSourceNamesToCloseTxOn, Transaction.Status.COMMIT);
}
private void closeTx(final Set<String> graphSourceNamesToCloseTxOn,
final Transaction.Status tx) {
final Set<Graph> graphsToCloseTxOn = new HashSet<>();
graphSourceNamesToCloseTxOn.forEach(r -> {
if (this.graphs.containsKey(r)) {
graphsToCloseTxOn.add(this.graphs.get(r));
}
});
graphsToCloseTxOn.forEach(graph -> {
if (graph.features().graph().supportsTransactions() &&
graph.tx().isOpen()) {
if (tx == Transaction.Status.COMMIT) {
graph.tx().commit();
} else {
graph.tx().rollback();
}
}
});
}
public boolean requireAuthentication() {
return this.authenticator.requireAuthentication();
}
public String authenticate(String username, String password) {
return this.authenticator.authenticate(username, password);
}
private void checkBackendVersionOrExit() {
for (Graph graph : this.graphs.values()) {
HugeGraph hugegraph = (HugeGraph) graph;
if (InMemoryDBStoreProvider.matchType(hugegraph.backend())) {
continue;
}
BackendStoreInfo info = new BackendStoreInfo(hugegraph);
if (!info.exist()) {
LOG.error("The backend store of '{}' has not been initialized",
hugegraph.name());
System.exit(-1);
}
if (!info.checkVersion()) {
System.exit(-1);
}
}
}
private void addMetrics(HugeConfig config) {
final MetricManager metrics = MetricManager.INSTANCE;
// Force add server reporter
ServerReporter reporter = ServerReporter.instance(metrics.getRegistry());
reporter.start(60L, TimeUnit.SECONDS);
// Add metrics for MAX_WRITE_THREADS
int maxWriteThreads = config.get(ServerOptions.MAX_WRITE_THREADS);
MetricsUtil.registerGauge(RestServer.class, "max-write-threads", () -> {
return maxWriteThreads;
});
// Add metrics for cache
Map<String, Cache> caches = CacheManager.instance().caches();
final AtomicInteger lastCaches = new AtomicInteger(caches.size());
MetricsUtil.registerGauge(Cache.class, "instances", () -> {
int count = caches.size();
if (count != lastCaches.get()) {
registerCacheMetrics();
} else {
lastCaches.set(count);
}
return count;
});
}
private void registerCacheMetrics() {
Map<String, Cache> caches = CacheManager.instance().caches();
final MetricRegistry registry = MetricManager.INSTANCE.getRegistry();
Set<String> names = registry.getNames();
for (Map.Entry<String, Cache> entry : caches.entrySet()) {
String key = entry.getKey();
Cache cache = entry.getValue();
String hits = String.format("%s.%s", key, "hits");
String miss = String.format("%s.%s", key, "miss");
String exp = String.format("%s.%s", key, "expire");
String size = String.format("%s.%s", key, "size");
String cap = String.format("%s.%s", key, "capacity");
// Avoid register multi times
if (names.stream().anyMatch(name -> name.endsWith(hits))) {
continue;
}
MetricsUtil.registerGauge(Cache.class, hits, () -> cache.hits());
MetricsUtil.registerGauge(Cache.class, miss, () -> cache.miss());
MetricsUtil.registerGauge(Cache.class, exp, () -> cache.expire());
MetricsUtil.registerGauge(Cache.class, size, () -> cache.size());
MetricsUtil.registerGauge(Cache.class, cap, () -> cache.capacity());
}
}
}

View File

@ -1,21 +1,25 @@
/*
* Copyright 2017 HugeGraph Authors
*
* 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
* 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.
* 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.hugegraph.store.node.metrics;
package com.baidu.hugegraph.metric;
import org.apache.tinkerpop.gremlin.server.util.MetricManager;
import com.codahale.metrics.Counter;
import com.codahale.metrics.Gauge;
@ -24,10 +28,10 @@ import com.codahale.metrics.Meter;
import com.codahale.metrics.MetricRegistry;
import com.codahale.metrics.Timer;
@Deprecated
public class MetricsUtil {
private static final MetricRegistry registry = new MetricRegistry();
private static final MetricRegistry registry =
MetricManager.INSTANCE.getRegistry();
public static <T> Gauge<T> registerGauge(Class<?> clazz, String name,
Gauge<T> gauge) {

Some files were not shown because too many files have changed in this diff Show More