Compare commits
77 Commits
MG-for-mrm
...
T610-FL-Ad
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
83aa71a29f | ||
|
|
c2a1328dcc | ||
|
|
b63db202d6 | ||
|
|
1abe8f8bfc | ||
|
|
4366085d89 | ||
|
|
9369ae9085 | ||
|
|
86a15331d1 | ||
|
|
0c8b35b151 | ||
|
|
11d60c203e | ||
|
|
38c0a08342 | ||
|
|
7e1d39bf86 | ||
|
|
dd85b428bf | ||
|
|
2f9ed0146e | ||
|
|
3e0e17d469 | ||
|
|
b57f91fcfc | ||
|
|
066a96c0ae | ||
|
|
1ae6b71c5f | ||
|
|
cbe15e7f44 | ||
|
|
65a7ba01da | ||
|
|
7a2bbd4bb3 | ||
|
|
589e0e098b | ||
|
|
41d4185156 | ||
|
|
599c0a641f | ||
|
|
1fb49c4865 | ||
|
|
df1485aeec | ||
|
|
b2e1056389 | ||
|
|
e4c9411e63 | ||
|
|
a0bc1371dd | ||
|
|
21ad5d4328 | ||
|
|
8e3ab1ad0f | ||
|
|
cccf32e79d | ||
|
|
22bd60c613 | ||
|
|
8059a3e653 | ||
|
|
a7f4c98bea | ||
|
|
483f4d04bd | ||
|
|
3e7aef432f | ||
|
|
10ea9c773e | ||
|
|
b782271be8 | ||
|
|
a8ffcfa046 | ||
|
|
7b78665cd8 | ||
|
|
4abaf27765 | ||
|
|
ea2806bd57 | ||
|
|
c8dbaf5979 | ||
|
|
17049ada09 | ||
|
|
1b619f51b2 | ||
|
|
537855a0b2 | ||
|
|
5822b44b15 | ||
|
|
bf01c58ed9 | ||
|
|
89a5566f3f | ||
|
|
29452f8774 | ||
|
|
60ad05acff | ||
|
|
4f593c7fca | ||
|
|
770ea1189a | ||
|
|
695bb343f1 | ||
|
|
12b4ec1589 | ||
|
|
b33d2c3940 | ||
|
|
477acad1f6 | ||
|
|
ddca2b40f5 | ||
|
|
4817be0add | ||
|
|
3fb7e5378d | ||
|
|
1d88893715 | ||
|
|
bd2c30fddc | ||
|
|
06e6ead4d2 | ||
|
|
728b37080d | ||
|
|
48a531aac1 | ||
|
|
914fc1a656 | ||
|
|
1d1c182c2d | ||
|
|
c6e19ec09f | ||
|
|
693dab78d2 | ||
|
|
69eca9b043 | ||
|
|
5aeaad198b | ||
|
|
b23f88c607 | ||
|
|
4fd8bdce4c | ||
|
|
265b203b00 | ||
|
|
661e5185d8 | ||
|
|
7348ad6800 | ||
|
|
6c00d146f2 |
@@ -1,7 +1,9 @@
|
||||
---
|
||||
Checks: '*,
|
||||
-abseil-string-find-str-contains,
|
||||
-altera-id-dependent-backward-branch,
|
||||
-altera-struct-pack-align,
|
||||
-altera-unroll-loops,
|
||||
-android-*,
|
||||
-cert-err58-cpp,
|
||||
-cppcoreguidelines-avoid-c-arrays,
|
||||
@@ -59,7 +61,9 @@ Checks: '*,
|
||||
-readability-magic-numbers,
|
||||
-readability-named-parameter,
|
||||
-misc-no-recursion,
|
||||
-concurrency-mt-unsafe'
|
||||
-concurrency-mt-unsafe,
|
||||
-bugprone-easily-swappable-parameters'
|
||||
|
||||
WarningsAsErrors: ''
|
||||
HeaderFilterRegex: 'src/.*'
|
||||
AnalyzeTemporaryDtors: false
|
||||
@@ -86,4 +90,3 @@ CheckOptions:
|
||||
- key: modernize-use-nullptr.NullMacros
|
||||
value: 'NULL'
|
||||
...
|
||||
|
||||
|
||||
@@ -16,6 +16,7 @@ tmpdir=$(mktemp -d repo-XXXXXXXX)
|
||||
trap "rm -rf $tmpdir" EXIT INT
|
||||
|
||||
modified_files=$(git diff --cached --name-only --diff-filter=AM $against | sed -nE "/.*\.(cpp|cc|cxx|c|h|hpp)$/p")
|
||||
FAIL=0
|
||||
for file in $modified_files; do
|
||||
echo "Checking $file..."
|
||||
|
||||
@@ -23,21 +24,13 @@ for file in $modified_files; do
|
||||
|
||||
git checkout-index --prefix="$tmpdir/" -- $file
|
||||
|
||||
echo "Running clang-format..."
|
||||
$project_folder/tools/git-clang-format $tmpdir/$file
|
||||
code=$?
|
||||
|
||||
if [ $code -ne 0 ]; then
|
||||
break
|
||||
fi
|
||||
|
||||
# Do not break header checker
|
||||
echo "Running header checker..."
|
||||
$project_folder/tools/header-checker.py $tmpdir/$file $file --amend-year
|
||||
code=$?
|
||||
|
||||
if [ $code -ne 0 ]; then
|
||||
break
|
||||
CODE=$?
|
||||
if [ $CODE -ne 0 ]; then
|
||||
FAIL=1
|
||||
fi
|
||||
done;
|
||||
|
||||
return $code
|
||||
return ${FAIL}
|
||||
|
||||
5
.github/workflows/diff.yaml
vendored
5
.github/workflows/diff.yaml
vendored
@@ -1,4 +1,7 @@
|
||||
name: Diff
|
||||
concurrency:
|
||||
group: ${{ github.head_ref || github.sha }}
|
||||
cancel-in-progress: true
|
||||
|
||||
on:
|
||||
push:
|
||||
@@ -112,7 +115,7 @@ jobs:
|
||||
source /opt/toolchain-v4/activate
|
||||
|
||||
# Restrict clang-tidy results only to the modified parts
|
||||
git diff -U0 master... -- src ':!*.hpp' | ./tools/github/clang-tidy/clang-tidy-diff.py -p 1 -j $THREADS -path build | tee ./build/clang_tidy_output.txt
|
||||
git diff -U0 master... -- src | ./tools/github/clang-tidy/clang-tidy-diff.py -p 1 -j $THREADS -path build | tee ./build/clang_tidy_output.txt
|
||||
|
||||
# Fail if any warning is reported
|
||||
! cat ./build/clang_tidy_output.txt | ./tools/github/clang-tidy/grep_error_lines.sh > /dev/null
|
||||
|
||||
76
.github/workflows/package_all.yaml
vendored
76
.github/workflows/package_all.yaml
vendored
@@ -6,11 +6,11 @@ on: workflow_dispatch
|
||||
|
||||
jobs:
|
||||
centos-7:
|
||||
runs-on: [self-hosted, DockerMgBuild]
|
||||
runs-on: [self-hosted, DockerMgBuild, X64]
|
||||
timeout-minutes: 60
|
||||
steps:
|
||||
- name: "Set up repository"
|
||||
uses: actions/checkout@v2
|
||||
uses: actions/checkout@v3
|
||||
with:
|
||||
fetch-depth: 0 # Required because of release/get_version.py
|
||||
- name: "Build package"
|
||||
@@ -22,29 +22,29 @@ jobs:
|
||||
name: centos-7
|
||||
path: build/output/centos-7/memgraph*.rpm
|
||||
|
||||
centos-8:
|
||||
runs-on: [self-hosted, DockerMgBuild]
|
||||
centos-9:
|
||||
runs-on: [self-hosted, DockerMgBuild, X64]
|
||||
timeout-minutes: 60
|
||||
steps:
|
||||
- name: "Set up repository"
|
||||
uses: actions/checkout@v2
|
||||
uses: actions/checkout@v3
|
||||
with:
|
||||
fetch-depth: 0 # Required because of release/get_version.py
|
||||
- name: "Build package"
|
||||
run: |
|
||||
./release/package/run.sh package centos-8
|
||||
./release/package/run.sh package centos-9
|
||||
- name: "Upload package"
|
||||
uses: actions/upload-artifact@v2
|
||||
with:
|
||||
name: centos-8
|
||||
path: build/output/centos-8/memgraph*.rpm
|
||||
name: centos-9
|
||||
path: build/output/centos-9/memgraph*.rpm
|
||||
|
||||
debian-10:
|
||||
runs-on: [self-hosted, DockerMgBuild]
|
||||
runs-on: [self-hosted, DockerMgBuild, X64]
|
||||
timeout-minutes: 60
|
||||
steps:
|
||||
- name: "Set up repository"
|
||||
uses: actions/checkout@v2
|
||||
uses: actions/checkout@v3
|
||||
with:
|
||||
fetch-depth: 0 # Required because of release/get_version.py
|
||||
- name: "Build package"
|
||||
@@ -57,11 +57,11 @@ jobs:
|
||||
path: build/output/debian-10/memgraph*.deb
|
||||
|
||||
debian-11:
|
||||
runs-on: [self-hosted, DockerMgBuild]
|
||||
runs-on: [self-hosted, DockerMgBuild, X64]
|
||||
timeout-minutes: 60
|
||||
steps:
|
||||
- name: "Set up repository"
|
||||
uses: actions/checkout@v2
|
||||
uses: actions/checkout@v3
|
||||
with:
|
||||
fetch-depth: 0 # Required because of release/get_version.py
|
||||
- name: "Build package"
|
||||
@@ -74,11 +74,11 @@ jobs:
|
||||
path: build/output/debian-11/memgraph*.deb
|
||||
|
||||
docker:
|
||||
runs-on: [self-hosted, DockerMgBuild]
|
||||
runs-on: [self-hosted, DockerMgBuild, X64]
|
||||
timeout-minutes: 60
|
||||
steps:
|
||||
- name: "Set up repository"
|
||||
uses: actions/checkout@v2
|
||||
uses: actions/checkout@v3
|
||||
with:
|
||||
fetch-depth: 0 # Required because of release/get_version.py
|
||||
- name: "Build package"
|
||||
@@ -93,11 +93,11 @@ jobs:
|
||||
path: build/output/docker/memgraph*.tar.gz
|
||||
|
||||
ubuntu-1804:
|
||||
runs-on: [self-hosted, DockerMgBuild]
|
||||
runs-on: [self-hosted, DockerMgBuild, X64]
|
||||
timeout-minutes: 60
|
||||
steps:
|
||||
- name: "Set up repository"
|
||||
uses: actions/checkout@v2
|
||||
uses: actions/checkout@v3
|
||||
with:
|
||||
fetch-depth: 0 # Required because of release/get_version.py
|
||||
- name: "Build package"
|
||||
@@ -110,11 +110,11 @@ jobs:
|
||||
path: build/output/ubuntu-18.04/memgraph*.deb
|
||||
|
||||
ubuntu-2004:
|
||||
runs-on: [self-hosted, DockerMgBuild]
|
||||
runs-on: [self-hosted, DockerMgBuild, X64]
|
||||
timeout-minutes: 60
|
||||
steps:
|
||||
- name: "Set up repository"
|
||||
uses: actions/checkout@v2
|
||||
uses: actions/checkout@v3
|
||||
with:
|
||||
fetch-depth: 0 # Required because of release/get_version.py
|
||||
- name: "Build package"
|
||||
@@ -126,12 +126,29 @@ jobs:
|
||||
name: ubuntu-2004
|
||||
path: build/output/ubuntu-20.04/memgraph*.deb
|
||||
|
||||
debian-11-platform:
|
||||
runs-on: [self-hosted, DockerMgBuild]
|
||||
ubuntu-2204:
|
||||
runs-on: [self-hosted, DockerMgBuild, X64]
|
||||
timeout-minutes: 60
|
||||
steps:
|
||||
- name: "Set up repository"
|
||||
uses: actions/checkout@v2
|
||||
uses: actions/checkout@v3
|
||||
with:
|
||||
fetch-depth: 0 # Required because of release/get_version.py
|
||||
- name: "Build package"
|
||||
run: |
|
||||
./release/package/run.sh package ubuntu-22.04
|
||||
- name: "Upload package"
|
||||
uses: actions/upload-artifact@v2
|
||||
with:
|
||||
name: ubuntu-2204
|
||||
path: build/output/ubuntu-22.04/memgraph*.deb
|
||||
|
||||
debian-11-platform:
|
||||
runs-on: [self-hosted, DockerMgBuild, X64]
|
||||
timeout-minutes: 60
|
||||
steps:
|
||||
- name: "Set up repository"
|
||||
uses: actions/checkout@v3
|
||||
with:
|
||||
fetch-depth: 0 # Required because of release/get_version.py
|
||||
- name: "Build package"
|
||||
@@ -142,3 +159,20 @@ jobs:
|
||||
with:
|
||||
name: debian-11-platform
|
||||
path: build/output/debian-11/memgraph*.deb
|
||||
|
||||
debian-11-arm:
|
||||
runs-on: [self-hosted, DockerMgBuild, ARM64, strange]
|
||||
timeout-minutes: 60
|
||||
steps:
|
||||
- name: "Set up repository"
|
||||
uses: actions/checkout@v3
|
||||
with:
|
||||
fetch-depth: 0 # Required because of release/get_version.py
|
||||
- name: "Build package"
|
||||
run: |
|
||||
./release/package/run.sh package debian-11-arm
|
||||
- name: "Upload package"
|
||||
uses: actions/upload-artifact@v2
|
||||
with:
|
||||
name: debian-11
|
||||
path: build/output/debian-11/memgraph*.deb
|
||||
|
||||
49
.github/workflows/release_docker.yaml
vendored
Normal file
49
.github/workflows/release_docker.yaml
vendored
Normal file
@@ -0,0 +1,49 @@
|
||||
name: Publish Docker images
|
||||
|
||||
on:
|
||||
workflow_dispatch:
|
||||
inputs:
|
||||
version:
|
||||
description: "Memgraph binary version to publish on Dockerhub."
|
||||
required: true
|
||||
|
||||
jobs:
|
||||
docker_publish:
|
||||
runs-on: ubuntu-latest
|
||||
env:
|
||||
DOCKER_ORGANIZATION_NAME: memgraph
|
||||
DOCKER_REPOSITORY_NAME: memgraph
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v2
|
||||
|
||||
- name: Set up QEMU
|
||||
uses: docker/setup-qemu-action@v1
|
||||
|
||||
- name: Set up Docker Buildx
|
||||
id: buildx
|
||||
uses: docker/setup-buildx-action@v1
|
||||
|
||||
- name: Log in to Docker Hub
|
||||
uses: docker/login-action@v1
|
||||
with:
|
||||
username: ${{ secrets.DOCKER_USERNAME }}
|
||||
password: ${{ secrets.DOCKER_PASSWORD }}
|
||||
|
||||
- name: Download memgraph binary
|
||||
run: |
|
||||
cd release/docker
|
||||
curl -L https://download.memgraph.com/memgraph/v${{ github.event.inputs.version }}/debian-11/memgraph_${{ github.event.inputs.version }}-1_amd64.deb > memgraph-amd64.deb
|
||||
curl -L https://download.memgraph.com/memgraph/v${{ github.event.inputs.version }}/debian-11-aarch64/memgraph_${{ github.event.inputs.version }}-1_arm64.deb > memgraph-arm64.deb
|
||||
|
||||
- name: Build & push docker images
|
||||
run: |
|
||||
cd release/docker
|
||||
docker buildx build \
|
||||
--build-arg BINARY_NAME="memgraph-" \
|
||||
--build-arg EXTENSION="deb" \
|
||||
--platform linux/amd64,linux/arm64 \
|
||||
--tag $DOCKER_ORGANIZATION_NAME/$DOCKER_REPOSITORY_NAME:${{ github.event.inputs.version }} \
|
||||
--tag $DOCKER_ORGANIZATION_NAME/$DOCKER_REPOSITORY_NAME:latest \
|
||||
--file memgraph_deb.dockerfile \
|
||||
--push .
|
||||
2
.gitignore
vendored
2
.gitignore
vendored
@@ -9,6 +9,7 @@
|
||||
*.swn
|
||||
*.swo
|
||||
*.swp
|
||||
|
||||
*~
|
||||
.DS_Store
|
||||
.gdb_history
|
||||
@@ -26,6 +27,7 @@ src/query/frontend/opencypher/generated/
|
||||
tags
|
||||
ve/
|
||||
ve3/
|
||||
.cache/
|
||||
perf.data*
|
||||
TAGS
|
||||
*.apollo_measurements
|
||||
|
||||
24
.pre-commit-config.yaml
Normal file
24
.pre-commit-config.yaml
Normal file
@@ -0,0 +1,24 @@
|
||||
repos:
|
||||
- repo: https://github.com/pre-commit/pre-commit-hooks
|
||||
rev: v2.3.0
|
||||
hooks:
|
||||
- id: check-yaml
|
||||
- id: end-of-file-fixer
|
||||
- id: trailing-whitespace
|
||||
- repo: https://github.com/psf/black
|
||||
rev: 22.3.0
|
||||
hooks:
|
||||
- id: black
|
||||
args: # arguments to configure black
|
||||
- --line-length=120
|
||||
- --include='\.pyi?$'
|
||||
# these folders wont be formatted by black
|
||||
- --exclude="""\.git |
|
||||
\.__pycache__|
|
||||
build|
|
||||
libs|
|
||||
.cache"""
|
||||
- repo: https://github.com/pre-commit/mirrors-clang-format
|
||||
rev: v13.0.0
|
||||
hooks:
|
||||
- id: clang-format
|
||||
@@ -184,7 +184,8 @@ set(CMAKE_CXX_STANDARD_REQUIRED ON)
|
||||
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wall \
|
||||
-Werror=switch -Werror=switch-bool -Werror=return-type \
|
||||
-Werror=return-stack-address \
|
||||
-Wno-c99-designator")
|
||||
-Wno-c99-designator \
|
||||
-DBOOST_ASIO_USE_TS_EXECUTOR_AS_DEFAULT")
|
||||
|
||||
# Don't omit frame pointer in RelWithDebInfo, for additional callchain debug.
|
||||
set(CMAKE_CXX_FLAGS_RELWITHDEBINFO
|
||||
@@ -204,6 +205,8 @@ set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -fuse-ld=gold")
|
||||
# release flags
|
||||
set(CMAKE_CXX_FLAGS_RELEASE "-O2 -DNDEBUG")
|
||||
|
||||
SET(CMAKE_CXX_LINK_FLAGS "${CMAKE_CXX_LINK_FLAGS} -pthread")
|
||||
|
||||
#debug flags
|
||||
set(PREFERRED_DEBUGGER "gdb" CACHE STRING
|
||||
"Tunes the debug output for your preferred debugger (gdb or lldb).")
|
||||
@@ -228,6 +231,8 @@ endif()
|
||||
message(STATUS "CMake build type: ${CMAKE_BUILD_TYPE}")
|
||||
# -----------------------------------------------------------------------------
|
||||
|
||||
set(MG_ARCH "x86_64" CACHE STRING "Host architecture to build Memgraph on. Supported values are x86_64 (default), ARM64.")
|
||||
|
||||
# setup external dependencies -------------------------------------------------
|
||||
|
||||
# threading
|
||||
|
||||
@@ -1 +1 @@
|
||||
* @gitbuda @antonio2368 @antaljanosbenjamin @kostasrim @jbajic
|
||||
* @antaljanosbenjamin @kostasrim
|
||||
|
||||
12
README.md
12
README.md
@@ -54,6 +54,18 @@ Memgraph is implemented in C/C++ and leverages an in-memory first architecture
|
||||
to ensure that you’re getting the best possible performance consistently and
|
||||
without surprises. It’s also ACID-compliant and highly available.
|
||||
|
||||
## :video_game: Memgraph Playground
|
||||
|
||||
You don't need to install anything to try out Memgraph. Check out
|
||||
our **[Memgraph Playground](https://playground.memgraph.com/)** sandboxes in
|
||||
your browser.
|
||||
|
||||
<p align="left">
|
||||
<a href="https://playground.memgraph.com/">
|
||||
<img width="450px" alt="Memgraph Playground" src="https://download.memgraph.com/asset/github/memgraph/memgraph-playground.png">
|
||||
</a>
|
||||
</p>
|
||||
|
||||
## :floppy_disk: Download & Install
|
||||
|
||||
### Windows
|
||||
|
||||
@@ -47,6 +47,14 @@ modifications:
|
||||
value: ""
|
||||
override: false
|
||||
|
||||
- name: "bolt_cert_file"
|
||||
value: "/etc/memgraph/ssl/cert.pem"
|
||||
override: false
|
||||
|
||||
- name: "bolt_key_file"
|
||||
value: "/etc/memgraph/ssl/key.pem"
|
||||
override: false
|
||||
|
||||
- name: "storage_properties_on_edges"
|
||||
value: "true"
|
||||
override: true
|
||||
|
||||
@@ -18,14 +18,16 @@ WIDTH = 80
|
||||
|
||||
def wrap_text(s, initial_indent="# "):
|
||||
return "\n#\n".join(
|
||||
map(lambda x: textwrap.fill(x, WIDTH, initial_indent=initial_indent,
|
||||
subsequent_indent="# "), s.split("\n")))
|
||||
map(
|
||||
lambda x: textwrap.fill(x, WIDTH, initial_indent=initial_indent, subsequent_indent="# "),
|
||||
s.split("\n"),
|
||||
)
|
||||
)
|
||||
|
||||
|
||||
def extract_flags(binary_path):
|
||||
ret = {}
|
||||
data = subprocess.run([binary_path, "--help-xml"],
|
||||
stdout=subprocess.PIPE).stdout.decode("utf-8")
|
||||
data = subprocess.run([binary_path, "--help-xml"], stdout=subprocess.PIPE).stdout.decode("utf-8")
|
||||
root = ET.fromstring(data)
|
||||
for child in root:
|
||||
if child.tag == "usage" and child.text.lower().count("warning"):
|
||||
@@ -46,8 +48,7 @@ def apply_config_to_flags(config, flags):
|
||||
for modification in config["modifications"]:
|
||||
name = modification["name"]
|
||||
if name not in flags:
|
||||
print("WARNING: Flag '" + name + "' missing from binary!",
|
||||
file=sys.stderr)
|
||||
print("WARNING: Flag '" + name + "' missing from binary!", file=sys.stderr)
|
||||
continue
|
||||
flags[name]["default"] = modification["value"]
|
||||
flags[name]["override"] = modification["override"]
|
||||
@@ -75,8 +76,9 @@ def extract_sections(flags):
|
||||
else:
|
||||
sections.append((current_section, current_flags))
|
||||
sections.append(("other", other))
|
||||
assert set(sum(map(lambda x: x[1], sections), [])) == set(flags.keys()), \
|
||||
"The section extraction algorithm lost some flags!"
|
||||
assert set(sum(map(lambda x: x[1], sections), [])) == set(
|
||||
flags.keys()
|
||||
), "The section extraction algorithm lost some flags!"
|
||||
return sections
|
||||
|
||||
|
||||
@@ -89,8 +91,7 @@ def generate_config_file(sections, flags):
|
||||
helpstr = flag["meaning"] + " [" + flag["type"] + "]"
|
||||
ret += wrap_text(helpstr) + "\n"
|
||||
prefix = "# " if not flag["override"] else ""
|
||||
ret += prefix + "--" + flag["name"].replace("_", "-") + \
|
||||
"=" + flag["default"] + "\n\n"
|
||||
ret += prefix + "--" + flag["name"].replace("_", "-") + "=" + flag["default"] + "\n\n"
|
||||
ret += "\n"
|
||||
ret += wrap_text(config["footer"])
|
||||
return ret.strip() + "\n"
|
||||
@@ -98,13 +99,16 @@ def generate_config_file(sections, flags):
|
||||
|
||||
if __name__ == "__main__":
|
||||
parser = argparse.ArgumentParser()
|
||||
parser.add_argument("memgraph_binary",
|
||||
help="path to Memgraph binary")
|
||||
parser.add_argument("output_file",
|
||||
help="path where to store the generated Memgraph "
|
||||
"configuration file")
|
||||
parser.add_argument("--config-file", default=CONFIG_FILE,
|
||||
help="path to generator configuration file")
|
||||
parser.add_argument("memgraph_binary", help="path to Memgraph binary")
|
||||
parser.add_argument(
|
||||
"output_file",
|
||||
help="path where to store the generated Memgraph " "configuration file",
|
||||
)
|
||||
parser.add_argument(
|
||||
"--config-file",
|
||||
default=CONFIG_FILE,
|
||||
help="path to generator configuration file",
|
||||
)
|
||||
|
||||
args = parser.parse_args()
|
||||
flags = extract_flags(args.memgraph_binary)
|
||||
|
||||
@@ -11,7 +11,7 @@ TOOLCHAIN_BUILD_DEPS=(
|
||||
gnupg2 # used for archive signature verification
|
||||
tar gzip bzip2 xz unzip # used for archive unpacking
|
||||
zlib-devel # zlib library used for all builds
|
||||
expat-devel libipt-devel libbabeltrace-devel xz-devel python3-devel # gdb
|
||||
expat-devel libipt libipt-devel libbabeltrace-devel xz-devel python3-devel # gdb
|
||||
texinfo # gdb
|
||||
libcurl-devel # cmake
|
||||
curl # snappy
|
||||
@@ -22,6 +22,7 @@ TOOLCHAIN_BUILD_DEPS=(
|
||||
openssl-devel
|
||||
gmp-devel
|
||||
gperf
|
||||
patch
|
||||
)
|
||||
|
||||
TOOLCHAIN_RUN_DEPS=(
|
||||
@@ -105,7 +106,7 @@ install() {
|
||||
https://repo.ius.io/ius-release-el7.rpm
|
||||
yum update -y
|
||||
yum install -y wget python3 python3-pip
|
||||
yum install -y git224
|
||||
yum install -y git
|
||||
for pkg in $1; do
|
||||
if [ "$pkg" == libipt ]; then
|
||||
if ! yum list installed libipt >/dev/null 2>/dev/null; then
|
||||
|
||||
@@ -6,14 +6,12 @@ DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" >/dev/null 2>&1 && pwd )"
|
||||
source "$DIR/../util.sh"
|
||||
|
||||
TOOLCHAIN_BUILD_DEPS=(
|
||||
coreutils gcc gcc-c++ make # generic build tools
|
||||
coreutils-common gcc gcc-c++ make # generic build tools
|
||||
wget # used for archive download
|
||||
gnupg2 # used for archive signature verification
|
||||
tar gzip bzip2 xz unzip # used for archive unpacking
|
||||
zlib-devel # zlib library used for all builds
|
||||
expat-devel libipt-devel libbabeltrace-devel xz-devel python36-devel texinfo # for gdb
|
||||
libcurl-devel # for cmake
|
||||
curl # snappy
|
||||
expat-devel xz-devel python3-devel texinfo libbabeltrace-devel # for gdb
|
||||
readline-devel # for cmake and llvm
|
||||
libffi-devel libxml2-devel # for llvm
|
||||
libedit-devel pcre-devel automake bison # for swig
|
||||
@@ -21,28 +19,32 @@ TOOLCHAIN_BUILD_DEPS=(
|
||||
openssl-devel
|
||||
gmp-devel
|
||||
gperf
|
||||
diffutils
|
||||
libipt libipt-devel # intel
|
||||
patch
|
||||
)
|
||||
|
||||
TOOLCHAIN_RUN_DEPS=(
|
||||
make # generic build tools
|
||||
tar gzip bzip2 xz # used for archive unpacking
|
||||
zlib # zlib library used for all builds
|
||||
expat libipt libbabeltrace xz-libs python36 # for gdb
|
||||
expat xz-libs python3 # for gdb
|
||||
readline # for cmake and llvm
|
||||
libffi libxml2 # for llvm
|
||||
openssl-devel
|
||||
perl # for openssl
|
||||
)
|
||||
|
||||
MEMGRAPH_BUILD_DEPS=(
|
||||
git # source code control
|
||||
make pkgconf-pkg-config # build system
|
||||
curl wget # for downloading libs
|
||||
wget # for downloading libs
|
||||
libuuid-devel java-11-openjdk # required by antlr
|
||||
readline-devel # for memgraph console
|
||||
python36-devel # for query modules
|
||||
python3-devel # for query modules
|
||||
openssl-devel
|
||||
libseccomp-devel
|
||||
python36 python3-virtualenv python3-pip nmap-ncat # for qa, macro_benchmark and stress tests
|
||||
python3 python3-pip python3-virtualenv nmap-ncat # for qa, macro_benchmark and stress tests
|
||||
#
|
||||
# IMPORTANT: python3-yaml does NOT exist on CentOS
|
||||
# Install it manually using `pip3 install PyYAML`
|
||||
@@ -51,7 +53,7 @@ MEMGRAPH_BUILD_DEPS=(
|
||||
libcurl-devel # mg-requests
|
||||
rpm-build rpmlint # for RPM package building
|
||||
doxygen graphviz # source documentation generators
|
||||
which mono-complete dotnet-sdk-3.1 nodejs golang zip unzip java-11-openjdk-devel # for driver tests
|
||||
which nodejs golang zip unzip java-11-openjdk-devel # for driver tests
|
||||
sbcl # for custom Lisp C++ preprocessing
|
||||
autoconf # for jemalloc code generation
|
||||
libtool # for protobuf code generation
|
||||
@@ -70,6 +72,9 @@ check() {
|
||||
fi
|
||||
continue
|
||||
fi
|
||||
if [ "$pkg" == "python3-virtualenv" ]; then
|
||||
continue
|
||||
fi
|
||||
if ! yum list installed "$pkg" >/dev/null 2>/dev/null; then
|
||||
missing="$pkg $missing"
|
||||
fi
|
||||
@@ -93,12 +98,13 @@ install() {
|
||||
else
|
||||
echo "NOTE: export LANG=en_US.utf8"
|
||||
fi
|
||||
dnf install -y epel-release
|
||||
dnf install -y 'dnf-command(config-manager)'
|
||||
dnf config-manager --set-enabled powertools # Required to install texinfo.
|
||||
dnf update -y
|
||||
dnf install -y wget git python36 python3-pip
|
||||
yum update -y
|
||||
yum install -y wget git python3 python3-pip
|
||||
for pkg in $1; do
|
||||
# Since there is no support for libipt-devel for CentOS 9 we install
|
||||
# Fedoras version of same libs, they are the same version but released
|
||||
# for different OS
|
||||
# TODO Update when libipt-devel releases for CentOS 9
|
||||
if [ "$pkg" == libipt ]; then
|
||||
if ! dnf list installed libipt >/dev/null 2>/dev/null; then
|
||||
dnf install -y http://repo.okay.com.mx/centos/8/x86_64/release/libipt-1.6.1-8.el8.x86_64.rpm
|
||||
@@ -106,19 +112,14 @@ install() {
|
||||
continue
|
||||
fi
|
||||
if [ "$pkg" == libipt-devel ]; then
|
||||
if ! yum list installed libipt-devel >/dev/null 2>/dev/null; then
|
||||
if ! dnf list installed libipt-devel >/dev/null 2>/dev/null; then
|
||||
dnf install -y http://repo.okay.com.mx/centos/8/x86_64/release/libipt-devel-1.6.1-8.el8.x86_64.rpm
|
||||
fi
|
||||
continue
|
||||
fi
|
||||
# Install GDB dependencies not present in the standard repos.
|
||||
# https://bugs.centos.org/view.php?id=17068
|
||||
# https://centos.pkgs.org
|
||||
# Since 2020, there is Babeltrace2 (https://babeltrace.org). Not used
|
||||
# within GDB yet (an assumption).
|
||||
if [ "$pkg" == libbabeltrace-devel ]; then
|
||||
if ! dnf list installed libbabeltrace-devel >/dev/null 2>/dev/null; then
|
||||
dnf install -y http://mirror.centos.org/centos/8/PowerTools/x86_64/os/Packages/libbabeltrace-devel-1.5.4-3.el8.x86_64.rpm
|
||||
dnf install -y http://mirror.stream.centos.org/9-stream/CRB/x86_64/os/Packages/libbabeltrace-devel-1.5.8-10.el9.x86_64.rpm
|
||||
fi
|
||||
continue
|
||||
fi
|
||||
@@ -134,15 +135,6 @@ install() {
|
||||
fi
|
||||
continue
|
||||
fi
|
||||
if [ "$pkg" == dotnet-sdk-3.1 ]; then
|
||||
if ! dnf list installed dotnet-sdk-3.1 >/dev/null 2>/dev/null; then
|
||||
wget -nv https://packages.microsoft.com/config/centos/8/packages-microsoft-prod.rpm -O packages-microsoft-prod.rpm
|
||||
rpm -Uvh https://packages.microsoft.com/config/centos/8/packages-microsoft-prod.rpm
|
||||
dnf update -y
|
||||
dnf install -y dotnet-sdk-3.1
|
||||
fi
|
||||
continue
|
||||
fi
|
||||
if [ "$pkg" == PyYAML ]; then
|
||||
if [ -z ${SUDO_USER+x} ]; then # Running as root (e.g. Docker).
|
||||
pip3 install --user PyYAML
|
||||
@@ -151,7 +143,17 @@ install() {
|
||||
fi
|
||||
continue
|
||||
fi
|
||||
dnf install -y "$pkg"
|
||||
if [ "$pkg" == python3-virtualenv ]; then
|
||||
if [ -z ${SUDO_USER+x} ]; then # Running as root (e.g. Docker).
|
||||
pip3 install virtualenv
|
||||
pip3 install virtualenvwrapper
|
||||
else # Running using sudo.
|
||||
sudo -H -u "$SUDO_USER" bash -c "pip3 install virtualenv"
|
||||
sudo -H -u "$SUDO_USER" bash -c "pip3 install virtualenvwrapper"
|
||||
fi
|
||||
continue
|
||||
fi
|
||||
yum install -y "$pkg"
|
||||
done
|
||||
}
|
||||
|
||||
95
environment/os/debian-11-arm.sh
Executable file
95
environment/os/debian-11-arm.sh
Executable file
@@ -0,0 +1,95 @@
|
||||
#!/bin/bash
|
||||
|
||||
set -Eeuo pipefail
|
||||
|
||||
DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" >/dev/null 2>&1 && pwd )"
|
||||
source "$DIR/../util.sh"
|
||||
|
||||
TOOLCHAIN_BUILD_DEPS=(
|
||||
coreutils gcc g++ build-essential make # generic build tools
|
||||
wget # used for archive download
|
||||
gnupg # used for archive signature verification
|
||||
tar gzip bzip2 xz-utils unzip # used for archive unpacking
|
||||
zlib1g-dev # zlib library used for all builds
|
||||
libexpat1-dev liblzma-dev python3-dev texinfo # for gdb
|
||||
libcurl4-openssl-dev # for cmake
|
||||
libreadline-dev # for cmake and llvm
|
||||
libffi-dev libxml2-dev # for llvm
|
||||
libedit-dev libpcre3-dev automake bison # for swig
|
||||
curl # snappy
|
||||
file # for libunwind
|
||||
libssl-dev # for libevent
|
||||
libgmp-dev
|
||||
gperf # for proxygen
|
||||
git # for fbthrift
|
||||
)
|
||||
|
||||
TOOLCHAIN_RUN_DEPS=(
|
||||
make # generic build tools
|
||||
tar gzip bzip2 xz-utils # used for archive unpacking
|
||||
zlib1g # zlib library used for all builds
|
||||
libexpat1 liblzma5 python3 # for gdb
|
||||
libcurl4 # for cmake
|
||||
file # for CPack
|
||||
libreadline8 # for cmake and llvm
|
||||
libffi7 libxml2 # for llvm
|
||||
libssl-dev # for libevent
|
||||
)
|
||||
|
||||
MEMGRAPH_BUILD_DEPS=(
|
||||
git # source code control
|
||||
make pkg-config # build system
|
||||
curl wget # for downloading libs
|
||||
uuid-dev default-jre-headless # required by antlr
|
||||
libreadline-dev # for memgraph console
|
||||
libpython3-dev python3-dev # for query modules
|
||||
libssl-dev
|
||||
libseccomp-dev
|
||||
netcat # tests are using nc to wait for memgraph
|
||||
python3 virtualenv python3-virtualenv python3-pip # for qa, macro_benchmark and stress tests
|
||||
python3-yaml # for the configuration generator
|
||||
libcurl4-openssl-dev # mg-requests
|
||||
sbcl # for custom Lisp C++ preprocessing
|
||||
doxygen graphviz # source documentation generators
|
||||
mono-runtime mono-mcs zip unzip default-jdk-headless # for driver tests
|
||||
golang nodejs npm
|
||||
autoconf # for jemalloc code generation
|
||||
libtool # for protobuf code generation
|
||||
)
|
||||
|
||||
list() {
|
||||
echo "$1"
|
||||
}
|
||||
|
||||
check() {
|
||||
check_all_dpkg "$1"
|
||||
}
|
||||
|
||||
install() {
|
||||
cat >/etc/apt/sources.list <<EOF
|
||||
deb http://deb.debian.org/debian bullseye main
|
||||
deb-src http://deb.debian.org/debian bullseye main
|
||||
|
||||
deb http://deb.debian.org/debian-security/ bullseye-security main
|
||||
deb-src http://deb.debian.org/debian-security/ bullseye-security main
|
||||
|
||||
deb http://deb.debian.org/debian bullseye-updates main
|
||||
deb-src http://deb.debian.org/debian bullseye-updates main
|
||||
EOF
|
||||
cd "$DIR"
|
||||
apt update
|
||||
# If GitHub Actions runner is installed, append LANG to the environment.
|
||||
# Python related tests doesn't work the LANG export.
|
||||
if [ -d "/home/gh/actions-runner" ]; then
|
||||
echo "LANG=en_US.utf8" >> /home/gh/actions-runner/.env
|
||||
else
|
||||
echo "NOTE: export LANG=en_US.utf8"
|
||||
fi
|
||||
apt install -y wget
|
||||
for pkg in $1; do
|
||||
apt install -y "$pkg"
|
||||
done
|
||||
}
|
||||
|
||||
deps=$2"[*]"
|
||||
"$1" "${!deps}"
|
||||
@@ -87,7 +87,7 @@ EOF
|
||||
fi
|
||||
apt install -y wget
|
||||
for pkg in $1; do
|
||||
if [ "$pkg" == dotnet-sdk-3.1 ]; then
|
||||
if [ "$pkg" == dotnet-sdk-3.1 ]; then
|
||||
if ! dpkg -s "$pkg" 2>/dev/null >/dev/null; then
|
||||
wget -nv https://packages.microsoft.com/config/debian/10/packages-microsoft-prod.deb -O packages-microsoft-prod.deb
|
||||
dpkg -i packages-microsoft-prod.deb
|
||||
|
||||
93
environment/os/ubuntu-22.04.sh
Executable file
93
environment/os/ubuntu-22.04.sh
Executable file
@@ -0,0 +1,93 @@
|
||||
#!/bin/bash
|
||||
|
||||
set -Eeuo pipefail
|
||||
|
||||
DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" >/dev/null 2>&1 && pwd )"
|
||||
source "$DIR/../util.sh"
|
||||
|
||||
TOOLCHAIN_BUILD_DEPS=(
|
||||
coreutils gcc g++ build-essential make # generic build tools
|
||||
wget # used for archive download
|
||||
gnupg # used for archive signature verification
|
||||
tar gzip bzip2 xz-utils unzip # used for archive unpacking
|
||||
zlib1g-dev # zlib library used for all builds
|
||||
libexpat1-dev libipt-dev libbabeltrace-dev liblzma-dev python3-dev texinfo # for gdb
|
||||
libcurl4-openssl-dev # for cmake
|
||||
libreadline-dev # for cmake and llvm
|
||||
libffi-dev libxml2-dev # for llvm
|
||||
curl # snappy
|
||||
file
|
||||
git # for thrift
|
||||
libgmp-dev # for gdb
|
||||
gperf # for proxygen
|
||||
libssl-dev
|
||||
libedit-dev libpcre3-dev automake bison # for swig
|
||||
)
|
||||
|
||||
TOOLCHAIN_RUN_DEPS=(
|
||||
make # generic build tools
|
||||
tar gzip bzip2 xz-utils # used for archive unpacking
|
||||
zlib1g # zlib library used for all builds
|
||||
libexpat1 libipt2 libbabeltrace1 liblzma5 python3 # for gdb
|
||||
libcurl4 # for cmake
|
||||
libreadline8 # for cmake and llvm
|
||||
libffi7 libxml2 # for llvm
|
||||
libssl-dev # for libevent
|
||||
)
|
||||
|
||||
MEMGRAPH_BUILD_DEPS=(
|
||||
git # source code control
|
||||
make pkg-config # build system
|
||||
curl wget # for downloading libs
|
||||
uuid-dev default-jre-headless # required by antlr
|
||||
libreadline-dev # for memgraph console
|
||||
libpython3-dev python3-dev # for query modules
|
||||
libssl-dev
|
||||
libseccomp-dev
|
||||
netcat # tests are using nc to wait for memgraph
|
||||
python3 python3-virtualenv python3-pip # for qa, macro_benchmark and stress tests
|
||||
python3-yaml # for the configuration generator
|
||||
libcurl4-openssl-dev # mg-requests
|
||||
sbcl # for custom Lisp C++ preprocessing
|
||||
doxygen graphviz # source documentation generators
|
||||
mono-runtime mono-mcs zip unzip default-jdk-headless # for driver tests
|
||||
dotnet-sdk-6.0 golang nodejs npm
|
||||
autoconf # for jemalloc code generation
|
||||
libtool # for protobuf code generation
|
||||
)
|
||||
|
||||
list() {
|
||||
echo "$1"
|
||||
}
|
||||
|
||||
check() {
|
||||
check_all_dpkg "$1"
|
||||
}
|
||||
|
||||
install() {
|
||||
cd "$DIR"
|
||||
apt update
|
||||
# If GitHub Actions runner is installed, append LANG to the environment.
|
||||
# Python related tests doesn't work the LANG export.
|
||||
if [ -d "/home/gh/actions-runner" ]; then
|
||||
echo "LANG=en_US.utf8" >> /home/gh/actions-runner/.env
|
||||
else
|
||||
echo "NOTE: export LANG=en_US.utf8"
|
||||
fi
|
||||
apt install -y wget
|
||||
for pkg in $1; do
|
||||
if [ "$pkg" == dotnet-sdk-6.0 ]; then
|
||||
if ! dpkg -s dotnet-sdk-6.0 2>/dev/null >/dev/null; then
|
||||
wget -nv https://packages.microsoft.com/config/ubuntu/22.04/packages-microsoft-prod.deb -O packages-microsoft-prod.deb
|
||||
dpkg -i packages-microsoft-prod.deb
|
||||
apt-get update
|
||||
apt-get install -y apt-transport-https dotnet-sdk-6.0
|
||||
fi
|
||||
continue
|
||||
fi
|
||||
apt install -y "$pkg"
|
||||
done
|
||||
}
|
||||
|
||||
deps=$2"[*]"
|
||||
"$1" "${!deps}"
|
||||
41
environment/toolchain/folly.patch
Normal file
41
environment/toolchain/folly.patch
Normal file
@@ -0,0 +1,41 @@
|
||||
diff -ur a/folly/CMakeLists.txt b/folly/CMakeLists.txt
|
||||
--- a/folly/CMakeLists.txt 2021-12-12 23:10:42.000000000 +0100
|
||||
+++ b/folly/CMakeLists.txt 2022-02-03 15:19:41.349693134 +0100
|
||||
@@ -28,7 +28,6 @@
|
||||
)
|
||||
|
||||
add_subdirectory(experimental/exception_tracer)
|
||||
-add_subdirectory(logging/example)
|
||||
|
||||
if (PYTHON_EXTENSIONS)
|
||||
# Create tree of symbolic links in structure required for successful
|
||||
diff -ur a/folly/experimental/exception_tracer/ExceptionTracerLib.cpp b/folly/experimental/exception_tracer/ExceptionTracerLib.cpp
|
||||
--- a/folly/experimental/exception_tracer/ExceptionTracerLib.cpp 2021-12-12 23:10:42.000000000 +0100
|
||||
+++ b/folly/experimental/exception_tracer/ExceptionTracerLib.cpp 2022-02-03 15:19:11.003368891 +0100
|
||||
@@ -96,6 +96,7 @@
|
||||
#define __builtin_unreachable()
|
||||
#endif
|
||||
|
||||
+#if 0
|
||||
namespace __cxxabiv1 {
|
||||
|
||||
void __cxa_throw(
|
||||
@@ -154,5 +155,5 @@
|
||||
}
|
||||
|
||||
} // namespace std
|
||||
-
|
||||
+#endif
|
||||
#endif // defined(__GLIBCXX__)
|
||||
diff -ur a/folly/Portability.h b/folly/Portability.h
|
||||
--- a/folly/Portability.h 2021-12-12 23:10:42.000000000 +0100
|
||||
+++ b/folly/Portability.h 2022-02-03 15:19:11.003368891 +0100
|
||||
@@ -566,7 +566,7 @@
|
||||
#define FOLLY_HAS_COROUTINES 0
|
||||
#elif (__cpp_coroutines >= 201703L || __cpp_impl_coroutine >= 201902L) && \
|
||||
(__has_include(<coroutine>) || __has_include(<experimental/coroutine>))
|
||||
-#define FOLLY_HAS_COROUTINES 1
|
||||
+#define FOLLY_HAS_COROUTINES 0
|
||||
// This is mainly to workaround bugs triggered by LTO, when stack allocated
|
||||
// variables in await_suspend end up on a coroutine frame.
|
||||
#define FOLLY_CORO_AWAIT_SUSPEND_NONTRIVIAL_ATTRIBUTES FOLLY_NOINLINE
|
||||
@@ -1,2 +0,0 @@
|
||||
24d23
|
||||
< find_dependency(mvfst)
|
||||
11
environment/toolchain/proxygen.patch
Normal file
11
environment/toolchain/proxygen.patch
Normal file
@@ -0,0 +1,11 @@
|
||||
diff -ur a/cmake/proxygen-config.cmake.in b/cmake/proxygen-config.cmake.in
|
||||
--- a/cmake/proxygen-config.cmake.in 2021-12-13 02:37:05.000000000 +0100
|
||||
+++ b/cmake/proxygen-config.cmake.in 2022-01-27 17:14:28.284810621 +0100
|
||||
@@ -21,7 +21,6 @@
|
||||
find_dependency(folly)
|
||||
find_dependency(wangle)
|
||||
find_dependency(Fizz)
|
||||
-find_dependency(mvfst)
|
||||
# For now, anything that depends on Proxygen has to copy its FindZstd.cmake
|
||||
# and issue a `find_package(Zstd)`. Uncommenting this won't work because
|
||||
# this Zstd module exposes a library called `zstd`. The right fix is
|
||||
@@ -1,16 +0,0 @@
|
||||
55,57c55,57
|
||||
< # Disable RTTI.
|
||||
< string(REGEX REPLACE "/GR" "" CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS}")
|
||||
< set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} /GR-")
|
||||
---
|
||||
> # # Disable RTTI.
|
||||
> # string(REGEX REPLACE "/GR" "" CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS}")
|
||||
> # set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} /GR-")
|
||||
80,82c80,82
|
||||
< # Disable RTTI.
|
||||
< string(REGEX REPLACE "-frtti" "" CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS}")
|
||||
< set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fno-rtti")
|
||||
---
|
||||
> # # Disable RTTI.
|
||||
> # string(REGEX REPLACE "-frtti" "" CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS}")
|
||||
> # set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fno-rtti")
|
||||
29
environment/toolchain/snappy.patch
Normal file
29
environment/toolchain/snappy.patch
Normal file
@@ -0,0 +1,29 @@
|
||||
diff -ur a/CMakeLists.txt b/CMakeLists.txt
|
||||
--- a/CMakeLists.txt 2021-05-05 00:53:34.000000000 +0200
|
||||
+++ b/CMakeLists.txt 2022-01-27 17:18:34.758302398 +0100
|
||||
@@ -52,9 +52,9 @@
|
||||
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} /EHs-c-")
|
||||
add_definitions(-D_HAS_EXCEPTIONS=0)
|
||||
|
||||
- # Disable RTTI.
|
||||
- string(REGEX REPLACE "/GR" "" CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS}")
|
||||
- set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} /GR-")
|
||||
+ # # Disable RTTI.
|
||||
+ # string(REGEX REPLACE "/GR" "" CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS}")
|
||||
+ # set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} /GR-")
|
||||
else(CMAKE_CXX_COMPILER_ID STREQUAL "MSVC")
|
||||
# Use -Wall for clang and gcc.
|
||||
if(NOT CMAKE_CXX_FLAGS MATCHES "-Wall")
|
||||
@@ -77,9 +77,9 @@
|
||||
string(REGEX REPLACE "-fexceptions" "" CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS}")
|
||||
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fno-exceptions")
|
||||
|
||||
- # Disable RTTI.
|
||||
- string(REGEX REPLACE "-frtti" "" CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS}")
|
||||
- set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fno-rtti")
|
||||
+ # # Disable RTTI.
|
||||
+ # string(REGEX REPLACE "-frtti" "" CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS}")
|
||||
+ # set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fno-rtti")
|
||||
endif(CMAKE_CXX_COMPILER_ID STREQUAL "MSVC")
|
||||
|
||||
# BUILD_SHARED_LIBS is a standard CMake variable, but we declare it here to make
|
||||
@@ -10,6 +10,18 @@ cd "$DIR"
|
||||
source "$DIR/../util.sh"
|
||||
DISTRO="$(operating_system)"
|
||||
|
||||
for_arm=false
|
||||
if [[ "$#" -eq 1 ]]; then
|
||||
if [[ "$1" == "--for-arm" ]]; then
|
||||
for_arm=true
|
||||
else
|
||||
echo "Invalid argument received. Use '--for-arm' if you want to build the toolchain for ARM based CPU."
|
||||
exit 1
|
||||
fi
|
||||
fi
|
||||
|
||||
os="$1"
|
||||
|
||||
# toolchain version
|
||||
TOOLCHAIN_VERSION=4
|
||||
|
||||
@@ -21,7 +33,7 @@ case "$DISTRO" in
|
||||
GDB_VERSION=8.3
|
||||
;;
|
||||
*)
|
||||
GDB_VERSION=11.1
|
||||
GDB_VERSION=11.2
|
||||
;;
|
||||
esac
|
||||
CMAKE_VERSION=3.22.1
|
||||
@@ -169,36 +181,78 @@ if [ ! -f $PREFIX/bin/gcc ]; then
|
||||
pushd gcc-$GCC_VERSION
|
||||
./contrib/download_prerequisites
|
||||
mkdir build && pushd build
|
||||
# influenced by: https://buildd.debian.org/status/fetch.php?pkg=gcc-8&arch=amd64&ver=8.3.0-6&stamp=1554588545
|
||||
../configure -v \
|
||||
--build=x86_64-linux-gnu \
|
||||
--host=x86_64-linux-gnu \
|
||||
--target=x86_64-linux-gnu \
|
||||
--prefix=$PREFIX \
|
||||
--disable-multilib \
|
||||
--with-system-zlib \
|
||||
--enable-checking=release \
|
||||
--enable-languages=c,c++,fortran \
|
||||
--enable-gold=yes \
|
||||
--enable-ld=yes \
|
||||
--enable-lto \
|
||||
--enable-bootstrap \
|
||||
--disable-vtable-verify \
|
||||
--disable-werror \
|
||||
--without-included-gettext \
|
||||
--enable-threads=posix \
|
||||
--enable-nls \
|
||||
--enable-clocale=gnu \
|
||||
--enable-libstdcxx-debug \
|
||||
--enable-libstdcxx-time=yes \
|
||||
--enable-gnu-unique-object \
|
||||
--enable-libmpx \
|
||||
--enable-plugin \
|
||||
--enable-default-pie \
|
||||
--with-target-system-zlib \
|
||||
--with-tune=generic \
|
||||
--without-cuda-driver
|
||||
#--program-suffix=$( printf "$GCC_VERSION" | cut -d '.' -f 1,2 ) \
|
||||
# influenced by: https://buildd.debian.org/status/fetch.php?pkg=gcc-11&arch=arm64&ver=11.2.0-14&stamp=1642052446&raw=0
|
||||
if [[ "$for_arm" = true ]]; then
|
||||
../configure -v \
|
||||
--prefix=$PREFIX \
|
||||
--disable-multilib \
|
||||
--with-system-zlib \
|
||||
--enable-languages=c,c++,fortran \
|
||||
--enable-gold=yes \
|
||||
--enable-ld=yes \
|
||||
--disable-vtable-verify \
|
||||
--enable-libmpx \
|
||||
--without-cuda-driver \
|
||||
--enable-shared \
|
||||
--enable-linker-build-id \
|
||||
--without-included-gettext \
|
||||
--enable-threads=posix \
|
||||
--enable-nls \
|
||||
--enable-bootstrap \
|
||||
--enable-clocale=gnu \
|
||||
--enable-libstdcxx-debug \
|
||||
--enable-libstdcxx-time=yes \
|
||||
--with-default-libstdcxx-abi=new \
|
||||
--enable-gnu-unique-object \
|
||||
--disable-libquadmath \
|
||||
--disable-libquadmath-support \
|
||||
--enable-plugin \
|
||||
--enable-default-pie \
|
||||
--with-system-zlib \
|
||||
--enable-libphobos-checking=release \
|
||||
--with-target-system-zlib=auto \
|
||||
--enable-objc-gc=auto \
|
||||
--enable-multiarch \
|
||||
--enable-fix-cortex-a53-843419 \
|
||||
--disable-werror \
|
||||
--enable-checking=release \
|
||||
--build=aarch64-linux-gnu \
|
||||
--host=aarch64-linux-gnu \
|
||||
--target=aarch64-linux-gnu \
|
||||
--with-build-config=bootstrap-lto-lean \
|
||||
--enable-link-serialization=4
|
||||
else
|
||||
# influenced by: https://buildd.debian.org/status/fetch.php?pkg=gcc-8&arch=amd64&ver=8.3.0-6&stamp=1554588545
|
||||
../configure -v \
|
||||
--build=x86_64-linux-gnu \
|
||||
--host=x86_64-linux-gnu \
|
||||
--target=x86_64-linux-gnu \
|
||||
--prefix=$PREFIX \
|
||||
--disable-multilib \
|
||||
--with-system-zlib \
|
||||
--enable-checking=release \
|
||||
--enable-languages=c,c++,fortran \
|
||||
--enable-gold=yes \
|
||||
--enable-ld=yes \
|
||||
--enable-lto \
|
||||
--enable-bootstrap \
|
||||
--disable-vtable-verify \
|
||||
--disable-werror \
|
||||
--without-included-gettext \
|
||||
--enable-threads=posix \
|
||||
--enable-nls \
|
||||
--enable-clocale=gnu \
|
||||
--enable-libstdcxx-debug \
|
||||
--enable-libstdcxx-time=yes \
|
||||
--enable-gnu-unique-object \
|
||||
--enable-libmpx \
|
||||
--enable-plugin \
|
||||
--enable-default-pie \
|
||||
--with-target-system-zlib \
|
||||
--with-tune=generic \
|
||||
--without-cuda-driver
|
||||
#--program-suffix=$( printf "$GCC_VERSION" | cut -d '.' -f 1,2 ) \
|
||||
fi
|
||||
make -j$CPUS
|
||||
# make -k check # run test suite
|
||||
make install
|
||||
@@ -217,28 +271,56 @@ if [ ! -f $PREFIX/bin/ld.gold ]; then
|
||||
tar -xvf ../archives/binutils-$BINUTILS_VERSION.tar.gz
|
||||
pushd binutils-$BINUTILS_VERSION
|
||||
mkdir build && pushd build
|
||||
# influenced by: https://buildd.debian.org/status/fetch.php?pkg=binutils&arch=amd64&ver=2.32-7&stamp=1553247092
|
||||
env \
|
||||
CC=gcc \
|
||||
CXX=g++ \
|
||||
CFLAGS="-g -O2" \
|
||||
CXXFLAGS="-g -O2" \
|
||||
LDFLAGS="" \
|
||||
../configure \
|
||||
--build=x86_64-linux-gnu \
|
||||
--host=x86_64-linux-gnu \
|
||||
--prefix=$PREFIX \
|
||||
--enable-ld=default \
|
||||
--enable-gold \
|
||||
--enable-lto \
|
||||
--enable-plugins \
|
||||
--enable-shared \
|
||||
--enable-threads \
|
||||
--with-system-zlib \
|
||||
--enable-deterministic-archives \
|
||||
--disable-compressed-debug-sections \
|
||||
--enable-new-dtags \
|
||||
--disable-werror
|
||||
if [[ "$for_arm" = true ]]; then
|
||||
# influenced by: https://buildd.debian.org/status/fetch.php?pkg=binutils&arch=arm64&ver=2.37.90.20220130-2&stamp=1643576183&raw=0
|
||||
env \
|
||||
CC=gcc \
|
||||
CXX=g++ \
|
||||
CFLAGS="-g -O2" \
|
||||
CXXFLAGS="-g -O2" \
|
||||
LDFLAGS="" \
|
||||
../configure \
|
||||
--build=aarch64-linux-gnu \
|
||||
--host=aarch64-linux-gnu \
|
||||
--prefix=$PREFIX \
|
||||
--enable-ld=default \
|
||||
--enable-gold \
|
||||
--enable-lto \
|
||||
--enable-pgo-build=lto \
|
||||
--enable-plugins \
|
||||
--enable-shared \
|
||||
--enable-threads \
|
||||
--with-system-zlib \
|
||||
--enable-deterministic-archives \
|
||||
--disable-compressed-debug-sections \
|
||||
--disable-x86-used-note \
|
||||
--enable-obsolete \
|
||||
--enable-new-dtags \
|
||||
--disable-werror
|
||||
else
|
||||
# influenced by: https://buildd.debian.org/status/fetch.php?pkg=binutils&arch=amd64&ver=2.32-7&stamp=1553247092
|
||||
env \
|
||||
CC=gcc \
|
||||
CXX=g++ \
|
||||
CFLAGS="-g -O2" \
|
||||
CXXFLAGS="-g -O2" \
|
||||
LDFLAGS="" \
|
||||
../configure \
|
||||
--build=x86_64-linux-gnu \
|
||||
--host=x86_64-linux-gnu \
|
||||
--prefix=$PREFIX \
|
||||
--enable-ld=default \
|
||||
--enable-gold \
|
||||
--enable-lto \
|
||||
--enable-plugins \
|
||||
--enable-shared \
|
||||
--enable-threads \
|
||||
--with-system-zlib \
|
||||
--enable-deterministic-archives \
|
||||
--disable-compressed-debug-sections \
|
||||
--enable-new-dtags \
|
||||
--disable-werror
|
||||
fi
|
||||
make -j$CPUS
|
||||
# make -k check # run test suite
|
||||
make install
|
||||
@@ -253,34 +335,64 @@ if [ ! -f $PREFIX/bin/gdb ]; then
|
||||
tar -xvf ../archives/gdb-$GDB_VERSION.tar.gz
|
||||
pushd gdb-$GDB_VERSION
|
||||
mkdir build && pushd build
|
||||
# https://buildd.debian.org/status/fetch.php?pkg=gdb&arch=amd64&ver=8.2.1-2&stamp=1550831554&raw=0
|
||||
env \
|
||||
CC=gcc \
|
||||
CXX=g++ \
|
||||
CFLAGS="-g -O2 -fstack-protector-strong -Wformat -Werror=format-security" \
|
||||
CXXFLAGS="-g -O2 -fstack-protector-strong -Wformat -Werror=format-security" \
|
||||
CPPFLAGS="-Wdate-time -D_FORTIFY_SOURCE=2 -fPIC" \
|
||||
LDFLAGS="-Wl,-z,relro" \
|
||||
PYTHON="" \
|
||||
../configure \
|
||||
--build=x86_64-linux-gnu \
|
||||
--host=x86_64-linux-gnu \
|
||||
--prefix=$PREFIX \
|
||||
--disable-maintainer-mode \
|
||||
--disable-dependency-tracking \
|
||||
--disable-silent-rules \
|
||||
--disable-gdbtk \
|
||||
--disable-shared \
|
||||
--without-guile \
|
||||
--with-system-gdbinit=$PREFIX/etc/gdb/gdbinit \
|
||||
--with-system-readline \
|
||||
--with-expat \
|
||||
--with-system-zlib \
|
||||
--with-lzma \
|
||||
--with-babeltrace \
|
||||
--with-intel-pt \
|
||||
--enable-tui \
|
||||
--with-python=python3
|
||||
if [[ "$for_arm" = true ]]; then
|
||||
# https://buildd.debian.org/status/fetch.php?pkg=gdb&arch=arm64&ver=10.1-2&stamp=1614889767&raw=0
|
||||
env \
|
||||
CC=gcc \
|
||||
CXX=g++ \
|
||||
CFLAGS="-g -O2 -fstack-protector-strong -Wformat -Werror=format-security" \
|
||||
CXXFLAGS="-g -O2 -fstack-protector-strong -Wformat -Werror=format-security" \
|
||||
CPPFLAGS="-Wdate-time -D_FORTIFY_SOURCE=2 -fPIC" \
|
||||
LDFLAGS="-Wl,-z,relro" \
|
||||
PYTHON="" \
|
||||
../configure \
|
||||
--build=aarch64-linux-gnu \
|
||||
--host=aarch64-linux-gnu \
|
||||
--prefix=$PREFIX \
|
||||
--disable-maintainer-mode \
|
||||
--disable-dependency-tracking \
|
||||
--disable-silent-rules \
|
||||
--disable-gdbtk \
|
||||
--disable-shared \
|
||||
--without-guile \
|
||||
--with-system-gdbinit=$PREFIX/etc/gdb/gdbinit \
|
||||
--with-system-readline \
|
||||
--with-expat \
|
||||
--with-system-zlib \
|
||||
--with-lzma \
|
||||
--without-babeltrace \
|
||||
--enable-tui \
|
||||
--with-python=python3
|
||||
else
|
||||
# https://buildd.debian.org/status/fetch.php?pkg=gdb&arch=amd64&ver=8.2.1-2&stamp=1550831554&raw=0
|
||||
env \
|
||||
CC=gcc \
|
||||
CXX=g++ \
|
||||
CFLAGS="-g -O2 -fstack-protector-strong -Wformat -Werror=format-security" \
|
||||
CXXFLAGS="-g -O2 -fstack-protector-strong -Wformat -Werror=format-security" \
|
||||
CPPFLAGS="-Wdate-time -D_FORTIFY_SOURCE=2 -fPIC" \
|
||||
LDFLAGS="-Wl,-z,relro" \
|
||||
PYTHON="" \
|
||||
../configure \
|
||||
--build=x86_64-linux-gnu \
|
||||
--host=x86_64-linux-gnu \
|
||||
--prefix=$PREFIX \
|
||||
--disable-maintainer-mode \
|
||||
--disable-dependency-tracking \
|
||||
--disable-silent-rules \
|
||||
--disable-gdbtk \
|
||||
--disable-shared \
|
||||
--without-guile \
|
||||
--with-system-gdbinit=$PREFIX/etc/gdb/gdbinit \
|
||||
--with-system-readline \
|
||||
--with-expat \
|
||||
--with-system-zlib \
|
||||
--with-lzma \
|
||||
--with-babeltrace \
|
||||
--with-intel-pt \
|
||||
--enable-tui \
|
||||
--with-python=python3
|
||||
fi
|
||||
make -j$CPUS
|
||||
make install
|
||||
popd && popd
|
||||
@@ -424,8 +536,11 @@ if [ ! -f $PREFIX/bin/clang ]; then
|
||||
-DLLVM_BINUTILS_INCDIR=$PREFIX/include/ \
|
||||
-DLLVM_USE_PERF=yes
|
||||
make -j$CPUS
|
||||
make -j$CPUS check-clang # run clang test suite
|
||||
make -j$CPUS check-lld # run lld test suite
|
||||
if [[ "$for_arm" = false ]]; then
|
||||
make -j$CPUS check-clang # run clang test suite
|
||||
# ldd is not used
|
||||
# make -j$CPUS check-lld # run lld test suite
|
||||
fi
|
||||
make install
|
||||
popd && popd
|
||||
fi
|
||||
@@ -540,12 +655,12 @@ BZIP2_SHA256=a2848f34fcd5d6cf47def00461fcb528a0484d8edef8208d6d2e2909dc61d9cd
|
||||
BZIP2_VERSION=1.0.6
|
||||
DOUBLE_CONVERSION_SHA256=8a79e87d02ce1333c9d6c5e47f452596442a343d8c3e9b234e8a62fce1b1d49c
|
||||
DOUBLE_CONVERSION_VERSION=3.1.6
|
||||
FBLIBS_VERSION=2021.12.13.00
|
||||
FIZZ_SHA256=1f14665ea7434b7d0770985a2f64d688c5ddbeeaa85441ae3b38ccc7741d781c
|
||||
FBLIBS_VERSION=2022.01.31.00
|
||||
FIZZ_SHA256=32a60e78d41ea2682ce7e5d741b964f0ea83642656e42d4fea90c0936d6d0c7d
|
||||
FLEX_VERSION=2.6.4
|
||||
FMT_SHA256=b06ca3130158c625848f3fb7418f235155a4d389b2abc3a6245fb01cb0eb1e01
|
||||
FMT_VERSION=8.0.1
|
||||
FOLLY_SHA256=87f87f5c6bf101ef15322c7351039747fb73640504d3d6de1fb719428fb0a5bc
|
||||
FOLLY_SHA256=7b8d5dd2eb51757858247af0ad27af2e3e93823f84033a628722b01e06cd68a9
|
||||
GFLAGS_COMMIT_HASH=b37ceb03a0e56c9f15ce80409438a555f8a67b7c
|
||||
GLOG_SHA256=eede71f28371bf39aa69b45de23b329d37214016e2055269b3b5e7cfd40b59f5
|
||||
GLOG_VERSION=0.5.0
|
||||
@@ -556,13 +671,13 @@ LIBSODIUM_VERSION=1.0.18
|
||||
LIBUNWIND_VERSION=1.6.2
|
||||
LZ4_SHA256=33af5936ac06536805f9745e0b6d61da606a1f8b4cc5c04dd3cbaca3b9b4fc43
|
||||
LZ4_VERSION=1.8.3
|
||||
PROXYGEN_SHA256=301627955e23de21d466358ae736ba1302871a6dad6c7e1f8b99a04b5b728da3
|
||||
PROXYGEN_SHA256=5360a8ccdfb2f5a6c7b3eed331ec7ab0e2c792d579c6fff499c85c516c11fe14
|
||||
SNAPPY_SHA256=75c1fbb3d618dd3a0483bff0e26d0a92b495bbe5059c8b4f1c962b478b6e06e7
|
||||
SNAPPY_VERSION=1.1.9
|
||||
XZ_VERSION=5.2.5 # for LZMA
|
||||
ZLIB_VERSION=1.2.11
|
||||
ZLIB_VERSION=1.2.12
|
||||
ZSTD_VERSION=1.5.0
|
||||
WANGLE_SHA256=a8019f4efc4446b8e4769df757df34b14ad6e4937d3242fc3f853a9cc4e45e9c
|
||||
WANGLE_SHA256=1002e9c32b6f4837f6a760016e3b3e22f3509880ef3eaad191c80dc92655f23f
|
||||
|
||||
pushd archives
|
||||
|
||||
@@ -915,7 +1030,7 @@ if [ ! -f $PREFIX/include/snappy.h ]; then
|
||||
fi
|
||||
tar -xzf ../archives/snappy-$SNAPPY_VERSION.tar.gz
|
||||
pushd snappy-$SNAPPY_VERSION
|
||||
patch CMakeLists.txt ../../snappy.diff
|
||||
patch -p1 < ../../snappy.patch
|
||||
mkdir build
|
||||
pushd build
|
||||
cmake .. $COMMON_CMAKE_FLAGS \
|
||||
@@ -957,6 +1072,7 @@ if [ ! -d $PREFIX/include/folly ]; then
|
||||
mkdir folly-$FBLIBS_VERSION
|
||||
tar -xzf ../archives/folly-$FBLIBS_VERSION.tar.gz -C folly-$FBLIBS_VERSION
|
||||
pushd folly-$FBLIBS_VERSION
|
||||
patch -p1 < ../../folly.patch
|
||||
# build is used by facebook builder
|
||||
mkdir _build
|
||||
pushd _build
|
||||
@@ -1015,7 +1131,7 @@ if [ ! -d $PREFIX/include/proxygen ]; then
|
||||
mkdir proxygen-$FBLIBS_VERSION
|
||||
tar -xzf ../archives/proxygen-$FBLIBS_VERSION.tar.gz -C proxygen-$FBLIBS_VERSION
|
||||
pushd proxygen-$FBLIBS_VERSION
|
||||
patch cmake/proxygen-config.cmake.in ../../proxygen.diff
|
||||
patch -p1 < ../../proxygen.patch
|
||||
# build is used by facebook builder
|
||||
mkdir _build
|
||||
pushd _build
|
||||
@@ -1062,7 +1178,22 @@ popd
|
||||
|
||||
# create toolchain archive
|
||||
if [ ! -f $NAME-binaries-$DISTRO.tar.gz ]; then
|
||||
tar --owner=root --group=root -cpvzf $NAME-binaries-$DISTRO.tar.gz -C /opt $NAME
|
||||
DISTRO_FULL_NAME=${DISTRO}
|
||||
if [[ "${DISTRO}" == centos* ]]; then
|
||||
if [[ "$for_arm" = "true" ]]; then
|
||||
DISTRO_FULL_NAME="$DISTRO_FULL_NAME-aarch64"
|
||||
else
|
||||
DISTRO_FULL_NAME="$DISTRO_FULL_NAME-x86_64"
|
||||
fi
|
||||
else
|
||||
if [[ "$for_arm" = "true" ]]; then
|
||||
DISTRO_FULL_NAME="$DISTRO_FULL_NAME-arm64"
|
||||
else
|
||||
DISTRO_FULL_NAME="$DISTRO_FULL_NAME-amd64"
|
||||
fi
|
||||
fi
|
||||
|
||||
tar --owner=root --group=root -cpvzf $NAME-binaries-$DISTRO_FULL_NAME.tar.gz -C /opt $NAME
|
||||
fi
|
||||
|
||||
# output final instructions
|
||||
|
||||
@@ -5,6 +5,10 @@ operating_system() {
|
||||
sort | cut -d '=' -f 2- | sed 's/"//g' | paste -s -d '-'
|
||||
}
|
||||
|
||||
architecture() {
|
||||
uname -m
|
||||
}
|
||||
|
||||
check_all_yum() {
|
||||
local missing=""
|
||||
for pkg in $1; do
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
314
include/mgp.py
314
include/mgp.py
@@ -40,6 +40,7 @@ class InvalidContextError(Exception):
|
||||
"""
|
||||
Signals using a graph element instance outside of the registered procedure.
|
||||
"""
|
||||
|
||||
pass
|
||||
|
||||
|
||||
@@ -47,6 +48,7 @@ class UnknownError(_mgp.UnknownError):
|
||||
"""
|
||||
Signals unspecified failure.
|
||||
"""
|
||||
|
||||
pass
|
||||
|
||||
|
||||
@@ -54,6 +56,7 @@ class UnableToAllocateError(_mgp.UnableToAllocateError):
|
||||
"""
|
||||
Signals failed memory allocation.
|
||||
"""
|
||||
|
||||
pass
|
||||
|
||||
|
||||
@@ -61,6 +64,7 @@ class InsufficientBufferError(_mgp.InsufficientBufferError):
|
||||
"""
|
||||
Signals that some buffer is not big enough.
|
||||
"""
|
||||
|
||||
pass
|
||||
|
||||
|
||||
@@ -69,6 +73,7 @@ class OutOfRangeError(_mgp.OutOfRangeError):
|
||||
Signals that an index-like parameter has a value that is outside its
|
||||
possible values.
|
||||
"""
|
||||
|
||||
pass
|
||||
|
||||
|
||||
@@ -77,6 +82,7 @@ class LogicErrorError(_mgp.LogicErrorError):
|
||||
Signals faulty logic within the program such as violating logical
|
||||
preconditions or class invariants and may be preventable.
|
||||
"""
|
||||
|
||||
pass
|
||||
|
||||
|
||||
@@ -84,6 +90,7 @@ class DeletedObjectError(_mgp.DeletedObjectError):
|
||||
"""
|
||||
Signals accessing an already deleted object.
|
||||
"""
|
||||
|
||||
pass
|
||||
|
||||
|
||||
@@ -91,6 +98,7 @@ class InvalidArgumentError(_mgp.InvalidArgumentError):
|
||||
"""
|
||||
Signals that some of the arguments have invalid values.
|
||||
"""
|
||||
|
||||
pass
|
||||
|
||||
|
||||
@@ -98,6 +106,7 @@ class KeyAlreadyExistsError(_mgp.KeyAlreadyExistsError):
|
||||
"""
|
||||
Signals that a key already exists in a container-like object.
|
||||
"""
|
||||
|
||||
pass
|
||||
|
||||
|
||||
@@ -105,6 +114,7 @@ class ImmutableObjectError(_mgp.ImmutableObjectError):
|
||||
"""
|
||||
Signals modification of an immutable object.
|
||||
"""
|
||||
|
||||
pass
|
||||
|
||||
|
||||
@@ -112,6 +122,7 @@ class ValueConversionError(_mgp.ValueConversionError):
|
||||
"""
|
||||
Signals that the conversion failed between python and cypher values.
|
||||
"""
|
||||
|
||||
pass
|
||||
|
||||
|
||||
@@ -120,12 +131,14 @@ class SerializationError(_mgp.SerializationError):
|
||||
Signals serialization error caused by concurrent modifications from
|
||||
different transactions.
|
||||
"""
|
||||
|
||||
pass
|
||||
|
||||
|
||||
class Label:
|
||||
"""Label of a Vertex."""
|
||||
__slots__ = ('_name',)
|
||||
|
||||
__slots__ = ("_name",)
|
||||
|
||||
def __init__(self, name: str):
|
||||
self._name = name
|
||||
@@ -145,19 +158,22 @@ class Label:
|
||||
# Named property value of a Vertex or an Edge.
|
||||
# It would be better to use typing.NamedTuple with typed fields, but that is
|
||||
# not available in Python 3.5.
|
||||
Property = namedtuple('Property', ('name', 'value'))
|
||||
Property = namedtuple("Property", ("name", "value"))
|
||||
|
||||
|
||||
class Properties:
|
||||
"""
|
||||
A collection of properties either on a Vertex or an Edge.
|
||||
"""
|
||||
__slots__ = ('_vertex_or_edge', '_len',)
|
||||
|
||||
__slots__ = (
|
||||
"_vertex_or_edge",
|
||||
"_len",
|
||||
)
|
||||
|
||||
def __init__(self, vertex_or_edge):
|
||||
if not isinstance(vertex_or_edge, (_mgp.Vertex, _mgp.Edge)):
|
||||
raise TypeError("Expected '_mgp.Vertex' or '_mgp.Edge', \
|
||||
got {}".format(type(vertex_or_edge)))
|
||||
raise TypeError("Expected '_mgp.Vertex' or '_mgp.Edge', got {}".format(type(vertex_or_edge)))
|
||||
self._len = None
|
||||
self._vertex_or_edge = vertex_or_edge
|
||||
|
||||
@@ -330,7 +346,8 @@ class Properties:
|
||||
|
||||
class EdgeType:
|
||||
"""Type of an Edge."""
|
||||
__slots__ = ('_name',)
|
||||
|
||||
__slots__ = ("_name",)
|
||||
|
||||
def __init__(self, name):
|
||||
self._name = name
|
||||
@@ -348,7 +365,7 @@ class EdgeType:
|
||||
|
||||
|
||||
if sys.version_info >= (3, 5, 2):
|
||||
EdgeId = typing.NewType('EdgeId', int)
|
||||
EdgeId = typing.NewType("EdgeId", int)
|
||||
else:
|
||||
EdgeId = int
|
||||
|
||||
@@ -360,12 +377,12 @@ class Edge:
|
||||
a query. You should not globally store an instance of an Edge. Using an
|
||||
invalid Edge instance will raise InvalidContextError.
|
||||
"""
|
||||
__slots__ = ('_edge',)
|
||||
|
||||
__slots__ = ("_edge",)
|
||||
|
||||
def __init__(self, edge):
|
||||
if not isinstance(edge, _mgp.Edge):
|
||||
raise TypeError(
|
||||
"Expected '_mgp.Edge', got '{}'".format(type(edge)))
|
||||
raise TypeError("Expected '_mgp.Edge', got '{}'".format(type(edge)))
|
||||
self._edge = edge
|
||||
|
||||
def __deepcopy__(self, memo):
|
||||
@@ -408,7 +425,7 @@ class Edge:
|
||||
return EdgeType(self._edge.get_type_name())
|
||||
|
||||
@property
|
||||
def from_vertex(self) -> 'Vertex':
|
||||
def from_vertex(self) -> "Vertex":
|
||||
"""
|
||||
Get the source vertex.
|
||||
|
||||
@@ -419,7 +436,7 @@ class Edge:
|
||||
return Vertex(self._edge.from_vertex())
|
||||
|
||||
@property
|
||||
def to_vertex(self) -> 'Vertex':
|
||||
def to_vertex(self) -> "Vertex":
|
||||
"""
|
||||
Get the destination vertex.
|
||||
|
||||
@@ -453,7 +470,7 @@ class Edge:
|
||||
|
||||
|
||||
if sys.version_info >= (3, 5, 2):
|
||||
VertexId = typing.NewType('VertexId', int)
|
||||
VertexId = typing.NewType("VertexId", int)
|
||||
else:
|
||||
VertexId = int
|
||||
|
||||
@@ -465,12 +482,12 @@ class Vertex:
|
||||
in a query. You should not globally store an instance of a Vertex. Using an
|
||||
invalid Vertex instance will raise InvalidContextError.
|
||||
"""
|
||||
__slots__ = ('_vertex',)
|
||||
|
||||
__slots__ = ("_vertex",)
|
||||
|
||||
def __init__(self, vertex):
|
||||
if not isinstance(vertex, _mgp.Vertex):
|
||||
raise TypeError(
|
||||
"Expected '_mgp.Vertex', got '{}'".format(type(vertex)))
|
||||
raise TypeError("Expected '_mgp.Vertex', got '{}'".format(type(vertex)))
|
||||
self._vertex = vertex
|
||||
|
||||
def __deepcopy__(self, memo):
|
||||
@@ -513,8 +530,7 @@ class Vertex:
|
||||
"""
|
||||
if not self.is_valid():
|
||||
raise InvalidContextError()
|
||||
return tuple(Label(self._vertex.label_at(i))
|
||||
for i in range(self._vertex.labels_count()))
|
||||
return tuple(Label(self._vertex.label_at(i)) for i in range(self._vertex.labels_count()))
|
||||
|
||||
def add_label(self, label: str) -> None:
|
||||
"""
|
||||
@@ -615,7 +631,8 @@ class Vertex:
|
||||
|
||||
class Path:
|
||||
"""Path containing Vertex and Edge instances."""
|
||||
__slots__ = ('_path', '_vertices', '_edges')
|
||||
|
||||
__slots__ = ("_path", "_vertices", "_edges")
|
||||
|
||||
def __init__(self, starting_vertex_or_path: typing.Union[_mgp.Path, Vertex]):
|
||||
"""Initialize with a starting Vertex.
|
||||
@@ -636,8 +653,7 @@ class Path:
|
||||
raise InvalidContextError()
|
||||
self._path = _mgp.Path.make_with_start(vertex)
|
||||
else:
|
||||
raise TypeError("Expected '_mgp.Vertex' or '_mgp.Path', got '{}'"
|
||||
.format(type(starting_vertex_or_path)))
|
||||
raise TypeError("Expected '_mgp.Vertex' or '_mgp.Path', got '{}'".format(type(starting_vertex_or_path)))
|
||||
|
||||
def __copy__(self):
|
||||
if not self.is_valid():
|
||||
@@ -678,8 +694,7 @@ class Path:
|
||||
extension.
|
||||
"""
|
||||
if not isinstance(edge, Edge):
|
||||
raise TypeError(
|
||||
"Expected '_mgp.Edge', got '{}'".format(type(edge)))
|
||||
raise TypeError("Expected '_mgp.Edge', got '{}'".format(type(edge)))
|
||||
if not self.is_valid() or not edge.is_valid():
|
||||
raise InvalidContextError()
|
||||
self._path.expand(edge._edge)
|
||||
@@ -698,8 +713,7 @@ class Path:
|
||||
raise InvalidContextError()
|
||||
if self._vertices is None:
|
||||
num_vertices = self._path.size() + 1
|
||||
self._vertices = tuple(Vertex(self._path.vertex_at(i))
|
||||
for i in range(num_vertices))
|
||||
self._vertices = tuple(Vertex(self._path.vertex_at(i)) for i in range(num_vertices))
|
||||
return self._vertices
|
||||
|
||||
@property
|
||||
@@ -713,14 +727,14 @@ class Path:
|
||||
raise InvalidContextError()
|
||||
if self._edges is None:
|
||||
num_edges = self._path.size()
|
||||
self._edges = tuple(Edge(self._path.edge_at(i))
|
||||
for i in range(num_edges))
|
||||
self._edges = tuple(Edge(self._path.edge_at(i)) for i in range(num_edges))
|
||||
return self._edges
|
||||
|
||||
|
||||
class Record:
|
||||
"""Represents a record of resulting field values."""
|
||||
__slots__ = ('fields',)
|
||||
|
||||
__slots__ = ("fields",)
|
||||
|
||||
def __init__(self, **kwargs):
|
||||
"""Initialize with name=value fields in kwargs."""
|
||||
@@ -729,12 +743,12 @@ class Record:
|
||||
|
||||
class Vertices:
|
||||
"""Iterable over vertices in a graph."""
|
||||
__slots__ = ('_graph', '_len')
|
||||
|
||||
__slots__ = ("_graph", "_len")
|
||||
|
||||
def __init__(self, graph):
|
||||
if not isinstance(graph, _mgp.Graph):
|
||||
raise TypeError(
|
||||
"Expected '_mgp.Graph', got '{}'".format(type(graph)))
|
||||
raise TypeError("Expected '_mgp.Graph', got '{}'".format(type(graph)))
|
||||
self._graph = graph
|
||||
self._len = None
|
||||
|
||||
@@ -791,12 +805,12 @@ class Vertices:
|
||||
|
||||
class Graph:
|
||||
"""State of the graph database in current ProcCtx."""
|
||||
__slots__ = ('_graph',)
|
||||
|
||||
__slots__ = ("_graph",)
|
||||
|
||||
def __init__(self, graph):
|
||||
if not isinstance(graph, _mgp.Graph):
|
||||
raise TypeError(
|
||||
"Expected '_mgp.Graph', got '{}'".format(type(graph)))
|
||||
raise TypeError("Expected '_mgp.Graph', got '{}'".format(type(graph)))
|
||||
self._graph = graph
|
||||
|
||||
def __deepcopy__(self, memo):
|
||||
@@ -885,8 +899,7 @@ class Graph:
|
||||
raise InvalidContextError()
|
||||
self._graph.detach_delete_vertex(vertex._vertex)
|
||||
|
||||
def create_edge(self, from_vertex: Vertex, to_vertex: Vertex,
|
||||
edge_type: EdgeType) -> None:
|
||||
def create_edge(self, from_vertex: Vertex, to_vertex: Vertex, edge_type: EdgeType) -> None:
|
||||
"""
|
||||
Create an edge.
|
||||
|
||||
@@ -899,8 +912,7 @@ class Graph:
|
||||
"""
|
||||
if not self.is_valid():
|
||||
raise InvalidContextError()
|
||||
return Edge(self._graph.create_edge(from_vertex._vertex,
|
||||
to_vertex._vertex, edge_type.name))
|
||||
return Edge(self._graph.create_edge(from_vertex._vertex, to_vertex._vertex, edge_type.name))
|
||||
|
||||
def delete_edge(self, edge: Edge) -> None:
|
||||
"""
|
||||
@@ -918,6 +930,7 @@ class Graph:
|
||||
|
||||
class AbortError(Exception):
|
||||
"""Signals that the procedure was asked to abort its execution."""
|
||||
|
||||
pass
|
||||
|
||||
|
||||
@@ -927,12 +940,12 @@ class ProcCtx:
|
||||
Access to a ProcCtx is only valid during a single execution of a procedure
|
||||
in a query. You should not globally store a ProcCtx instance.
|
||||
"""
|
||||
__slots__ = ('_graph',)
|
||||
|
||||
__slots__ = ("_graph",)
|
||||
|
||||
def __init__(self, graph):
|
||||
if not isinstance(graph, _mgp.Graph):
|
||||
raise TypeError(
|
||||
"Expected '_mgp.Graph', got '{}'".format(type(graph)))
|
||||
raise TypeError("Expected '_mgp.Graph', got '{}'".format(type(graph)))
|
||||
self._graph = Graph(graph)
|
||||
|
||||
def is_valid(self) -> bool:
|
||||
@@ -969,8 +982,7 @@ LocalDateTime = datetime.datetime
|
||||
|
||||
Duration = datetime.timedelta
|
||||
|
||||
Any = typing.Union[bool, str, Number, Map, Path,
|
||||
list, Date, LocalTime, LocalDateTime, Duration]
|
||||
Any = typing.Union[bool, str, Number, Map, Path, list, Date, LocalTime, LocalDateTime, Duration]
|
||||
|
||||
List = typing.List
|
||||
|
||||
@@ -1003,7 +1015,7 @@ def _typing_to_cypher_type(type_):
|
||||
Date: _mgp.type_date(),
|
||||
LocalTime: _mgp.type_local_time(),
|
||||
LocalDateTime: _mgp.type_local_date_time(),
|
||||
Duration: _mgp.type_duration()
|
||||
Duration: _mgp.type_duration(),
|
||||
}
|
||||
try:
|
||||
return simple_types[type_]
|
||||
@@ -1021,14 +1033,14 @@ def _typing_to_cypher_type(type_):
|
||||
if type(None) in type_args:
|
||||
types = tuple(t for t in type_args if t is not type(None)) # noqa E721
|
||||
if len(types) == 1:
|
||||
type_arg, = types
|
||||
(type_arg,) = types
|
||||
else:
|
||||
# We cannot do typing.Union[*types], so do the equivalent
|
||||
# with __getitem__ which does not even need arg unpacking.
|
||||
type_arg = typing.Union.__getitem__(types)
|
||||
return _mgp.type_nullable(_typing_to_cypher_type(type_arg))
|
||||
elif complex_type == list:
|
||||
type_arg, = type_args
|
||||
(type_arg,) = type_args
|
||||
return _mgp.type_list(_typing_to_cypher_type(type_arg))
|
||||
raise UnsupportedTypingError(type_)
|
||||
else:
|
||||
@@ -1038,13 +1050,17 @@ def _typing_to_cypher_type(type_):
|
||||
# printed the same way. `typing.List[type]` is printed as such, while
|
||||
# `typing.Optional[type]` is printed as 'typing.Union[type, NoneType]'
|
||||
def parse_type_args(type_as_str):
|
||||
return tuple(map(str.strip,
|
||||
type_as_str[type_as_str.index('[') + 1: -1].split(',')))
|
||||
return tuple(
|
||||
map(
|
||||
str.strip,
|
||||
type_as_str[type_as_str.index("[") + 1 : -1].split(","),
|
||||
)
|
||||
)
|
||||
|
||||
def fully_qualified_name(cls):
|
||||
if cls.__module__ is None or cls.__module__ == 'builtins':
|
||||
if cls.__module__ is None or cls.__module__ == "builtins":
|
||||
return cls.__name__
|
||||
return cls.__module__ + '.' + cls.__name__
|
||||
return cls.__module__ + "." + cls.__name__
|
||||
|
||||
def get_simple_type(type_as_str):
|
||||
for simple_type, cypher_type in simple_types.items():
|
||||
@@ -1060,28 +1076,26 @@ def _typing_to_cypher_type(type_):
|
||||
pass
|
||||
|
||||
def parse_typing(type_as_str):
|
||||
if type_as_str.startswith('typing.Union'):
|
||||
if type_as_str.startswith("typing.Union"):
|
||||
type_args_as_str = parse_type_args(type_as_str)
|
||||
none_type_as_str = type(None).__name__
|
||||
if none_type_as_str in type_args_as_str:
|
||||
types = tuple(
|
||||
t for t in type_args_as_str if t != none_type_as_str)
|
||||
types = tuple(t for t in type_args_as_str if t != none_type_as_str)
|
||||
if len(types) == 1:
|
||||
type_arg_as_str, = types
|
||||
(type_arg_as_str,) = types
|
||||
else:
|
||||
type_arg_as_str = 'typing.Union[' + \
|
||||
', '.join(types) + ']'
|
||||
type_arg_as_str = "typing.Union[" + ", ".join(types) + "]"
|
||||
simple_type = get_simple_type(type_arg_as_str)
|
||||
if simple_type is not None:
|
||||
return _mgp.type_nullable(simple_type)
|
||||
return _mgp.type_nullable(parse_typing(type_arg_as_str))
|
||||
elif type_as_str.startswith('typing.List'):
|
||||
elif type_as_str.startswith("typing.List"):
|
||||
type_arg_as_str = parse_type_args(type_as_str)
|
||||
|
||||
if len(type_arg_as_str) > 1:
|
||||
# Nested object could be a type consisting of a list of types (e.g. mgp.Map)
|
||||
# so we need to join the parts.
|
||||
type_arg_as_str = ', '.join(type_arg_as_str)
|
||||
type_arg_as_str = ", ".join(type_arg_as_str)
|
||||
else:
|
||||
type_arg_as_str = type_arg_as_str[0]
|
||||
|
||||
@@ -1096,9 +1110,11 @@ def _typing_to_cypher_type(type_):
|
||||
|
||||
# Procedure registration
|
||||
|
||||
|
||||
class Deprecated:
|
||||
"""Annotate a resulting Record's field as deprecated."""
|
||||
__slots__ = ('field_type',)
|
||||
|
||||
__slots__ = ("field_type",)
|
||||
|
||||
def __init__(self, type_):
|
||||
self.field_type = type_
|
||||
@@ -1106,8 +1122,7 @@ class Deprecated:
|
||||
|
||||
def raise_if_does_not_meet_requirements(func: typing.Callable[..., Record]):
|
||||
if not callable(func):
|
||||
raise TypeError("Expected a callable object, got an instance of '{}'"
|
||||
.format(type(func)))
|
||||
raise TypeError("Expected a callable object, got an instance of '{}'".format(type(func)))
|
||||
if inspect.iscoroutinefunction(func):
|
||||
raise TypeError("Callable must not be 'async def' function")
|
||||
if sys.version_info >= (3, 6):
|
||||
@@ -1117,24 +1132,25 @@ def raise_if_does_not_meet_requirements(func: typing.Callable[..., Record]):
|
||||
raise NotImplementedError("Generator functions are not supported")
|
||||
|
||||
|
||||
def _register_proc(func: typing.Callable[..., Record],
|
||||
is_write: bool):
|
||||
def _register_proc(func: typing.Callable[..., Record], is_write: bool):
|
||||
raise_if_does_not_meet_requirements(func)
|
||||
register_func = (
|
||||
_mgp.Module.add_write_procedure if is_write
|
||||
else _mgp.Module.add_read_procedure)
|
||||
register_func = _mgp.Module.add_write_procedure if is_write else _mgp.Module.add_read_procedure
|
||||
sig = inspect.signature(func)
|
||||
params = tuple(sig.parameters.values())
|
||||
if params and params[0].annotation is ProcCtx:
|
||||
|
||||
@wraps(func)
|
||||
def wrapper(graph, args):
|
||||
return func(ProcCtx(graph), *args)
|
||||
|
||||
params = params[1:]
|
||||
mgp_proc = register_func(_mgp._MODULE, wrapper)
|
||||
else:
|
||||
|
||||
@wraps(func)
|
||||
def wrapper(graph, args):
|
||||
return func(*args)
|
||||
|
||||
mgp_proc = register_func(_mgp._MODULE, wrapper)
|
||||
for param in params:
|
||||
name = param.name
|
||||
@@ -1149,8 +1165,7 @@ def _register_proc(func: typing.Callable[..., Record],
|
||||
if sig.return_annotation is not sig.empty:
|
||||
record = sig.return_annotation
|
||||
if not isinstance(record, Record):
|
||||
raise TypeError("Expected '{}' to return 'mgp.Record', got '{}'"
|
||||
.format(func.__name__, type(record)))
|
||||
raise TypeError("Expected '{}' to return 'mgp.Record', got '{}'".format(func.__name__, type(record)))
|
||||
for name, type_ in record.fields.items():
|
||||
if isinstance(type_, Deprecated):
|
||||
cypher_type = _typing_to_cypher_type(type_.field_type)
|
||||
@@ -1164,16 +1179,15 @@ def read_proc(func: typing.Callable[..., Record]):
|
||||
"""
|
||||
Register `func` as a read-only procedure of the current module.
|
||||
|
||||
`read_proc` is meant to be used as a decorator function to register module
|
||||
procedures. The registered `func` needs to be a callable which optionally
|
||||
takes `ProcCtx` as the first argument. Other arguments of `func` will be
|
||||
bound to values passed in the cypherQuery. The full signature of `func`
|
||||
needs to be annotated with types. The return type must be
|
||||
`Record(field_name=type, ...)` and the procedure must produce either a
|
||||
complete Record or None. To mark a field as deprecated, use
|
||||
`Record(field_name=Deprecated(type), ...)`. Multiple records can be
|
||||
produced by returning an iterable of them. Registering generator functions
|
||||
is currently not supported.
|
||||
The decorator `read_proc` is meant to be used to register module procedures.
|
||||
The registered `func` needs to be a callable which optionally takes
|
||||
`ProcCtx` as its first argument. Other arguments of `func` will be bound to
|
||||
values passed in the cypherQuery. The full signature of `func` needs to be
|
||||
annotated with types. The return type must be `Record(field_name=type, ...)`
|
||||
and the procedure must produce either a complete Record or None. To mark a
|
||||
field as deprecated, use `Record(field_name=Deprecated(type), ...)`.
|
||||
Multiple records can be produced by returning an iterable of them.
|
||||
Registering generator functions is currently not supported.
|
||||
|
||||
Example usage.
|
||||
|
||||
@@ -1207,16 +1221,16 @@ def write_proc(func: typing.Callable[..., Record]):
|
||||
"""
|
||||
Register `func` as a writeable procedure of the current module.
|
||||
|
||||
`write_proc` is meant to be used as a decorator function to register module
|
||||
The decorator `write_proc` is meant to be used to register module
|
||||
procedures. The registered `func` needs to be a callable which optionally
|
||||
takes `ProcCtx` as the first argument. Other arguments of `func` will be
|
||||
bound to values passed in the cypherQuery. The full signature of `func`
|
||||
needs to be annotated with types. The return type must be
|
||||
`Record(field_name=type, ...)` and the procedure must produce either a
|
||||
complete Record or None. To mark a field as deprecated, use
|
||||
`Record(field_name=Deprecated(type), ...)`. Multiple records can be
|
||||
produced by returning an iterable of them. Registering generator functions
|
||||
is currently not supported.
|
||||
`Record(field_name=Deprecated(type), ...)`. Multiple records can be produced
|
||||
by returning an iterable of them. Registering generator functions is
|
||||
currently not supported.
|
||||
|
||||
Example usage.
|
||||
|
||||
@@ -1257,20 +1271,22 @@ class InvalidMessageError(Exception):
|
||||
"""
|
||||
Signals using a message instance outside of the registered transformation.
|
||||
"""
|
||||
|
||||
pass
|
||||
|
||||
|
||||
SOURCE_TYPE_KAFKA = _mgp.SOURCE_TYPE_KAFKA
|
||||
SOURCE_TYPE_PULSAR = _mgp.SOURCE_TYPE_PULSAR
|
||||
|
||||
|
||||
class Message:
|
||||
"""Represents a message from a stream."""
|
||||
__slots__ = ('_message',)
|
||||
|
||||
__slots__ = ("_message",)
|
||||
|
||||
def __init__(self, message):
|
||||
if not isinstance(message, _mgp.Message):
|
||||
raise TypeError(
|
||||
"Expected '_mgp.Message', got '{}'".format(type(message)))
|
||||
raise TypeError("Expected '_mgp.Message', got '{}'".format(type(message)))
|
||||
self._message = message
|
||||
|
||||
def __deepcopy__(self, memo):
|
||||
@@ -1353,17 +1369,18 @@ class Message:
|
||||
|
||||
class InvalidMessagesError(Exception):
|
||||
"""Signals using a messages instance outside of the registered transformation."""
|
||||
|
||||
pass
|
||||
|
||||
|
||||
class Messages:
|
||||
"""Represents a list of messages from a stream."""
|
||||
__slots__ = ('_messages',)
|
||||
|
||||
__slots__ = ("_messages",)
|
||||
|
||||
def __init__(self, messages):
|
||||
if not isinstance(messages, _mgp.Messages):
|
||||
raise TypeError(
|
||||
"Expected '_mgp.Messages', got '{}'".format(type(messages)))
|
||||
raise TypeError("Expected '_mgp.Messages', got '{}'".format(type(messages)))
|
||||
self._messages = messages
|
||||
|
||||
def __deepcopy__(self, memo):
|
||||
@@ -1395,12 +1412,12 @@ class TransCtx:
|
||||
Access to a TransCtx is only valid during a single execution of a transformation.
|
||||
You should not globally store a TransCtx instance.
|
||||
"""
|
||||
__slots__ = ('_graph')
|
||||
|
||||
__slots__ = "_graph"
|
||||
|
||||
def __init__(self, graph):
|
||||
if not isinstance(graph, _mgp.Graph):
|
||||
raise TypeError(
|
||||
"Expected '_mgp.Graph', got '{}'".format(type(graph)))
|
||||
raise TypeError("Expected '_mgp.Graph', got '{}'".format(type(graph)))
|
||||
self._graph = Graph(graph)
|
||||
|
||||
def is_valid(self) -> bool:
|
||||
@@ -1420,21 +1437,116 @@ def transformation(func: typing.Callable[..., Record]):
|
||||
params = tuple(sig.parameters.values())
|
||||
if not params or not params[0].annotation is Messages:
|
||||
if not len(params) == 2 or not params[1].annotation is Messages:
|
||||
raise NotImplementedError(
|
||||
"Valid signatures for transformations are (TransCtx, Messages) or (Messages)")
|
||||
raise NotImplementedError("Valid signatures for transformations are (TransCtx, Messages) or (Messages)")
|
||||
if params[0].annotation is TransCtx:
|
||||
|
||||
@wraps(func)
|
||||
def wrapper(graph, messages):
|
||||
return func(TransCtx(graph), messages)
|
||||
|
||||
_mgp._MODULE.add_transformation(wrapper)
|
||||
else:
|
||||
|
||||
@wraps(func)
|
||||
def wrapper(graph, messages):
|
||||
return func(messages)
|
||||
|
||||
_mgp._MODULE.add_transformation(wrapper)
|
||||
return func
|
||||
|
||||
|
||||
class FuncCtx:
|
||||
"""Context of a function being executed.
|
||||
|
||||
Access to a FuncCtx is only valid during a single execution of a function in
|
||||
a query. You should not globally store a FuncCtx instance. The graph object
|
||||
within the FuncCtx is not mutable.
|
||||
"""
|
||||
|
||||
__slots__ = "_graph"
|
||||
|
||||
def __init__(self, graph):
|
||||
if not isinstance(graph, _mgp.Graph):
|
||||
raise TypeError("Expected '_mgp.Graph', got '{}'".format(type(graph)))
|
||||
self._graph = Graph(graph)
|
||||
|
||||
def is_valid(self) -> bool:
|
||||
return self._graph.is_valid()
|
||||
|
||||
|
||||
def function(func: typing.Callable):
|
||||
"""
|
||||
Register `func` as a user-defined function in the current module.
|
||||
|
||||
The decorator `function` is meant to be used to register module functions.
|
||||
The registered `func` needs to be a callable which optionally takes
|
||||
`FuncCtx` as its first argument. Other arguments of `func` will be bound to
|
||||
values passed in the Cypher query. Only the funcion arguments need to be
|
||||
annotated with types. The return type doesn't need to be specified, but it
|
||||
has to be supported by `mgp.Any`. Registering generator functions is
|
||||
currently not supported.
|
||||
|
||||
Example usage.
|
||||
|
||||
```
|
||||
import mgp
|
||||
@mgp.function
|
||||
def func_example(context: mgp.FuncCtx,
|
||||
required_arg: str,
|
||||
optional_arg: mgp.Nullable[str] = None
|
||||
):
|
||||
return_args = [required_arg]
|
||||
if optional_arg is not None:
|
||||
return_args.append(optional_arg)
|
||||
# Return any kind of result supported by mgp.Any
|
||||
return return_args
|
||||
```
|
||||
|
||||
The example function above returns a list of provided arguments:
|
||||
* `required_arg` is always present and its value is the first argument of
|
||||
the function.
|
||||
* `optional_arg` is present if the second argument of the function is not
|
||||
`null`.
|
||||
Any errors can be reported by raising an Exception.
|
||||
|
||||
The function can be invoked in Cypher using the following calls:
|
||||
RETURN example.func_example("first argument", "second_argument");
|
||||
RETURN example.func_example("first argument");
|
||||
Naturally, you may pass in different arguments.
|
||||
"""
|
||||
raise_if_does_not_meet_requirements(func)
|
||||
register_func = _mgp.Module.add_function
|
||||
sig = inspect.signature(func)
|
||||
params = tuple(sig.parameters.values())
|
||||
if params and params[0].annotation is FuncCtx:
|
||||
|
||||
@wraps(func)
|
||||
def wrapper(graph, args):
|
||||
return func(FuncCtx(graph), *args)
|
||||
|
||||
params = params[1:]
|
||||
mgp_func = register_func(_mgp._MODULE, wrapper)
|
||||
else:
|
||||
|
||||
@wraps(func)
|
||||
def wrapper(graph, args):
|
||||
return func(*args)
|
||||
|
||||
mgp_func = register_func(_mgp._MODULE, wrapper)
|
||||
|
||||
for param in params:
|
||||
name = param.name
|
||||
type_ = param.annotation
|
||||
if type_ is param.empty:
|
||||
type_ = object
|
||||
cypher_type = _typing_to_cypher_type(type_)
|
||||
if param.default is param.empty:
|
||||
mgp_func.add_arg(name, cypher_type)
|
||||
else:
|
||||
mgp_func.add_opt_arg(name, cypher_type, param.default)
|
||||
return func
|
||||
|
||||
|
||||
def _wrap_exceptions():
|
||||
def wrap_function(func):
|
||||
@wraps(func)
|
||||
@@ -1463,6 +1575,7 @@ def _wrap_exceptions():
|
||||
raise ValueConversionError(e)
|
||||
except _mgp.SerializationError as e:
|
||||
raise SerializationError(e)
|
||||
|
||||
return wrapped_func
|
||||
|
||||
def wrap_prop_func(func):
|
||||
@@ -1473,11 +1586,16 @@ def _wrap_exceptions():
|
||||
if inspect.isfunction(obj):
|
||||
setattr(cls, name, wrap_function(obj))
|
||||
elif isinstance(obj, property):
|
||||
setattr(cls, name, property(
|
||||
wrap_prop_func(obj.fget),
|
||||
wrap_prop_func(obj.fset),
|
||||
wrap_prop_func(obj.fdel),
|
||||
obj.__doc__))
|
||||
setattr(
|
||||
cls,
|
||||
name,
|
||||
property(
|
||||
wrap_prop_func(obj.fget),
|
||||
wrap_prop_func(obj.fset),
|
||||
wrap_prop_func(obj.fdel),
|
||||
obj.__doc__,
|
||||
),
|
||||
)
|
||||
|
||||
def defined_in_this_module(obj: object):
|
||||
return getattr(obj, "__module__", "") == __name__
|
||||
|
||||
75
init
75
init
@@ -10,6 +10,8 @@ function print_help () {
|
||||
echo -e "Check for missing packages and setup the project.\n"
|
||||
echo "Optional arguments:"
|
||||
echo -e " -h\tdisplay this help and exit"
|
||||
echo -e " --without-libs-setup\tskip the step for setting up libs"
|
||||
echo -e " --wsl-quicklisp-proxy \"host:port\"\tquicklist HTTP proxy (this flag + HTTP proxy are required on WSL)"
|
||||
}
|
||||
|
||||
function setup_virtualenv () {
|
||||
@@ -22,7 +24,7 @@ function setup_virtualenv () {
|
||||
fi
|
||||
|
||||
# create new virtualenv
|
||||
virtualenv -p python3 ve3 || exit 1
|
||||
python3 -m virtualenv -p python3 ve3 || exit 1
|
||||
source ve3/bin/activate
|
||||
pip --timeout 1000 install -r requirements.txt || exit 1
|
||||
deactivate
|
||||
@@ -30,26 +32,47 @@ function setup_virtualenv () {
|
||||
popd > /dev/null
|
||||
}
|
||||
|
||||
if [[ $# -gt 1 ]]; then
|
||||
wsl_quicklisp_proxy=""
|
||||
setup_libs=true
|
||||
if [[ $# -eq 1 && "$1" == "-h" ]]; then
|
||||
print_help
|
||||
exit 1
|
||||
elif [[ $# -eq 1 ]]; then
|
||||
case "$1" in
|
||||
-h)
|
||||
print_help
|
||||
exit 0
|
||||
;;
|
||||
*)
|
||||
# unknown option
|
||||
print_help
|
||||
exit 1
|
||||
;;
|
||||
esac
|
||||
exit 0
|
||||
else
|
||||
while(($#)); do
|
||||
case "$1" in
|
||||
--wsl-quicklisp-proxy)
|
||||
shift
|
||||
if [[ $# -eq 0 ]]; then
|
||||
echo "Missing proxy URL"
|
||||
print_help
|
||||
exit 1
|
||||
fi
|
||||
wsl_quicklisp_proxy=":proxy \"http://$1/\""
|
||||
shift
|
||||
;;
|
||||
--without-libs-setup)
|
||||
shift
|
||||
setup_libs=false
|
||||
;;
|
||||
*)
|
||||
# unknown option
|
||||
echo "Invalid argument provided: $1"
|
||||
print_help
|
||||
exit 1
|
||||
;;
|
||||
esac
|
||||
done
|
||||
fi
|
||||
|
||||
DISTRO=$(operating_system)
|
||||
echo "ALL BUILD PACKAGES: $($DIR/environment/os/$DISTRO.sh list MEMGRAPH_BUILD_DEPS)"
|
||||
$DIR/environment/os/$DISTRO.sh check MEMGRAPH_BUILD_DEPS
|
||||
ARCHITECTURE=$(architecture)
|
||||
if [ "${ARCHITECTURE}" = "arm64" ] || [ "${ARCHITECTURE}" = "aarch64" ]; then
|
||||
OS_SCRIPT=$DIR/environment/os/$DISTRO-arm.sh
|
||||
else
|
||||
OS_SCRIPT=$DIR/environment/os/$DISTRO.sh
|
||||
fi
|
||||
echo "ALL BUILD PACKAGES: $($OS_SCRIPT list MEMGRAPH_BUILD_DEPS)"
|
||||
$OS_SCRIPT check MEMGRAPH_BUILD_DEPS
|
||||
echo "All packages are in-place..."
|
||||
|
||||
# create a default build directory
|
||||
@@ -66,7 +89,7 @@ if [[ ! -f "${quicklisp_install_dir}/setup.lisp" ]]; then
|
||||
echo \
|
||||
"
|
||||
(load \"${DIR}/quicklisp.lisp\")
|
||||
(quicklisp-quickstart:install :path \"${quicklisp_install_dir}\")
|
||||
(quicklisp-quickstart:install $wsl_quicklisp_proxy :path \"${quicklisp_install_dir}\")
|
||||
" | sbcl --script || exit 1
|
||||
rm -rf quicklisp.lisp || exit 1
|
||||
fi
|
||||
@@ -80,11 +103,13 @@ echo \
|
||||
(ql:quickload '(:lcp :lcp/test) :silent t)
|
||||
" | sbcl --script
|
||||
|
||||
# Setup libs (download).
|
||||
cd libs
|
||||
./cleanup.sh
|
||||
./setup.sh
|
||||
cd ..
|
||||
if [[ "$setup_libs" == "true" ]]; then
|
||||
# Setup libs (download).
|
||||
cd libs
|
||||
./cleanup.sh
|
||||
./setup.sh
|
||||
cd ..
|
||||
fi
|
||||
|
||||
# setup gql_behave dependencies
|
||||
setup_virtualenv tests/gql_behave
|
||||
@@ -110,3 +135,7 @@ for hook in $(find $DIR/.githooks -type f -printf "%f\n"); do
|
||||
ln -s -f "$DIR/.githooks/$hook" "$DIR/.git/hooks/$hook"
|
||||
echo "Added $hook hook"
|
||||
done;
|
||||
|
||||
# Install precommit hook
|
||||
python3 -m pip install pre-commit
|
||||
python3 -m pre_commit install
|
||||
|
||||
1
libs/.gitignore
vendored
1
libs/.gitignore
vendored
@@ -4,5 +4,4 @@
|
||||
!cleanup.sh
|
||||
!CMakeLists.txt
|
||||
!__main.cpp
|
||||
!jemalloc.cmake
|
||||
!pulsar.patch
|
||||
|
||||
@@ -245,3 +245,13 @@ import_external_library(pulsar STATIC
|
||||
-DUSE_LOG4CXX=OFF
|
||||
BUILD_COMMAND $(MAKE) pulsarStaticWithDeps)
|
||||
add_dependencies(pulsar-proj protobuf)
|
||||
|
||||
if (${MG_ARCH} STREQUAL "ARM64")
|
||||
set(MG_LIBRDTSC_CMAKE_ARGS -DLIBRDTSC_ARCH_x86=OFF -DLIBRDTSC_ARCH_ARM64=ON)
|
||||
endif()
|
||||
|
||||
import_external_library(librdtsc STATIC
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/librdtsc/lib/librdtsc.a
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/librdtsc/include
|
||||
CMAKE_ARGS ${MG_LIBRDTSC_CMAKE_ARGS}
|
||||
BUILD_COMMAND $(MAKE) rdtsc)
|
||||
|
||||
@@ -1,55 +0,0 @@
|
||||
set(JEMALLOC_DIR "${LIB_DIR}/jemalloc")
|
||||
|
||||
set(JEMALLOC_SRCS
|
||||
${JEMALLOC_DIR}/src/arena.c
|
||||
${JEMALLOC_DIR}/src/background_thread.c
|
||||
${JEMALLOC_DIR}/src/base.c
|
||||
${JEMALLOC_DIR}/src/bin.c
|
||||
${JEMALLOC_DIR}/src/bitmap.c
|
||||
${JEMALLOC_DIR}/src/ckh.c
|
||||
${JEMALLOC_DIR}/src/ctl.c
|
||||
${JEMALLOC_DIR}/src/div.c
|
||||
${JEMALLOC_DIR}/src/extent.c
|
||||
${JEMALLOC_DIR}/src/extent_dss.c
|
||||
${JEMALLOC_DIR}/src/extent_mmap.c
|
||||
${JEMALLOC_DIR}/src/hash.c
|
||||
${JEMALLOC_DIR}/src/hook.c
|
||||
${JEMALLOC_DIR}/src/jemalloc.c
|
||||
${JEMALLOC_DIR}/src/large.c
|
||||
${JEMALLOC_DIR}/src/log.c
|
||||
${JEMALLOC_DIR}/src/malloc_io.c
|
||||
${JEMALLOC_DIR}/src/mutex.c
|
||||
${JEMALLOC_DIR}/src/mutex_pool.c
|
||||
${JEMALLOC_DIR}/src/nstime.c
|
||||
${JEMALLOC_DIR}/src/pages.c
|
||||
${JEMALLOC_DIR}/src/prng.c
|
||||
${JEMALLOC_DIR}/src/prof.c
|
||||
${JEMALLOC_DIR}/src/rtree.c
|
||||
${JEMALLOC_DIR}/src/sc.c
|
||||
${JEMALLOC_DIR}/src/stats.c
|
||||
${JEMALLOC_DIR}/src/sz.c
|
||||
${JEMALLOC_DIR}/src/tcache.c
|
||||
${JEMALLOC_DIR}/src/test_hooks.c
|
||||
${JEMALLOC_DIR}/src/ticker.c
|
||||
${JEMALLOC_DIR}/src/tsd.c
|
||||
${JEMALLOC_DIR}/src/witness.c
|
||||
${JEMALLOC_DIR}/src/safety_check.c
|
||||
)
|
||||
|
||||
add_library(jemalloc ${JEMALLOC_SRCS})
|
||||
target_include_directories(jemalloc PUBLIC "${JEMALLOC_DIR}/include")
|
||||
|
||||
find_package(Threads REQUIRED)
|
||||
target_link_libraries(jemalloc PUBLIC Threads::Threads)
|
||||
|
||||
target_compile_definitions(jemalloc PRIVATE -DJEMALLOC_NO_PRIVATE_NAMESPACE)
|
||||
|
||||
if (CMAKE_BUILD_TYPE STREQUAL "DEBUG")
|
||||
target_compile_definitions(jemalloc PRIVATE -DJEMALLOC_DEBUG=1 -DJEMALLOC_PROF=1)
|
||||
endif()
|
||||
|
||||
target_compile_options(jemalloc PRIVATE -Wno-redundant-decls)
|
||||
# for RTLD_NEXT
|
||||
target_compile_definitions(jemalloc PRIVATE _GNU_SOURCE)
|
||||
|
||||
set_property(TARGET jemalloc APPEND PROPERTY INTERFACE_COMPILE_DEFINITIONS USE_JEMALLOC=1)
|
||||
29
libs/librdtsc.patch
Normal file
29
libs/librdtsc.patch
Normal file
@@ -0,0 +1,29 @@
|
||||
diff --git a/CMakeLists.txt b/CMakeLists.txt
|
||||
index ee9b58c..31359a9 100644
|
||||
--- a/CMakeLists.txt
|
||||
+++ b/CMakeLists.txt
|
||||
@@ -48,7 +48,7 @@ option(LIBRDTSC_USE_PMU "Enables PMU usage on ARM platforms" OFF)
|
||||
# | Library Build and Install Properties |
|
||||
# +--------------------------------------------------------+
|
||||
|
||||
-add_library(rdtsc SHARED
|
||||
+add_library(rdtsc
|
||||
src/cycles.c
|
||||
src/common_timer.c
|
||||
src/timer.c
|
||||
@@ -72,15 +72,6 @@ target_include_directories(rdtsc
|
||||
PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}/include
|
||||
)
|
||||
|
||||
-# Install directory changes depending on build mode
|
||||
-if (CMAKE_BUILD_TYPE MATCHES "^[Dd]ebug")
|
||||
- # During debug, the library will be installed into a local directory
|
||||
- set(CMAKE_INSTALL_PREFIX ${CMAKE_CURRENT_BINARY_DIR}/_install CACHE PATH "" FORCE)
|
||||
-else ()
|
||||
- # This will install in /usr/lib and /usr/include
|
||||
- set(CMAKE_INSTALL_PREFIX /usr CACHE PATH "" FORCE)
|
||||
-endif ()
|
||||
-
|
||||
# Specifying what to export when installing (GNUInstallDirs required)
|
||||
install(TARGETS rdtsc
|
||||
EXPORT librstsc-config
|
||||
@@ -107,26 +107,21 @@ declare -A primary_urls=(
|
||||
["antlr4-code"]="http://$local_cache_host/git/antlr4.git"
|
||||
["antlr4-generator"]="http://$local_cache_host/file/antlr-4.9.2-complete.jar"
|
||||
["cppitertools"]="http://$local_cache_host/git/cppitertools.git"
|
||||
["fmt"]="http://$local_cache_host/git/fmt.git"
|
||||
["rapidcheck"]="http://$local_cache_host/git/rapidcheck.git"
|
||||
["gbenchmark"]="http://$local_cache_host/git/benchmark.git"
|
||||
["gtest"]="http://$local_cache_host/git/googletest.git"
|
||||
["gflags"]="http://$local_cache_host/git/gflags.git"
|
||||
["libbcrypt"]="http://$local_cache_host/git/libbcrypt.git"
|
||||
["bzip2"]="http://$local_cache_host/git/bzip2.git"
|
||||
["zlib"]="http://$local_cache_host/git/zlib.git"
|
||||
["rocksdb"]="http://$local_cache_host/git/rocksdb.git"
|
||||
["mgclient"]="http://$local_cache_host/git/mgclient.git"
|
||||
["pymgclient"]="http://$local_cache_host/git/pymgclient.git"
|
||||
["mgconsole"]="http://$local_cache_host/git/mgconsole.git"
|
||||
["spdlog"]="http://$local_cache_host/git/spdlog"
|
||||
["jemalloc"]="http://$local_cache_host/git/jemalloc.git"
|
||||
["nlohmann"]="http://$local_cache_host/file/nlohmann/json/4f8fba14066156b73f1189a2b8bd568bde5284c5/single_include/nlohmann/json.hpp"
|
||||
["neo4j"]="http://$local_cache_host/file/neo4j-community-3.2.3-unix.tar.gz"
|
||||
["librdkafka"]="http://$local_cache_host/git/librdkafka.git"
|
||||
["protobuf"]="http://$local_cache_host/git/protobuf.git"
|
||||
["boost"]="http://$local_cache_host/file/boost_1_77_0.tar.gz"
|
||||
["pulsar"]="http://$local_cache_host/git/pulsar.git"
|
||||
["librdtsc"]="http://$local_cache_host/git/librdtsc.git"
|
||||
)
|
||||
|
||||
# The goal of secondary urls is to have links to the "source of truth" of
|
||||
@@ -137,26 +132,21 @@ declare -A secondary_urls=(
|
||||
["antlr4-code"]="https://github.com/antlr/antlr4.git"
|
||||
["antlr4-generator"]="http://www.antlr.org/download/antlr-4.9.2-complete.jar"
|
||||
["cppitertools"]="https://github.com/ryanhaining/cppitertools.git"
|
||||
["fmt"]="https://github.com/fmtlib/fmt.git"
|
||||
["rapidcheck"]="https://github.com/emil-e/rapidcheck.git"
|
||||
["gbenchmark"]="https://github.com/google/benchmark.git"
|
||||
["gtest"]="https://github.com/google/googletest.git"
|
||||
["gflags"]="https://github.com/memgraph/gflags.git"
|
||||
["libbcrypt"]="https://github.com/rg3/libbcrypt"
|
||||
["bzip2"]="https://github.com/VFR-maniac/bzip2"
|
||||
["zlib"]="https://github.com/madler/zlib.git"
|
||||
["rocksdb"]="https://github.com/facebook/rocksdb.git"
|
||||
["mgclient"]="https://github.com/memgraph/mgclient.git"
|
||||
["pymgclient"]="https://github.com/memgraph/pymgclient.git"
|
||||
["mgconsole"]="http://github.com/memgraph/mgconsole.git"
|
||||
["spdlog"]="https://github.com/gabime/spdlog"
|
||||
["jemalloc"]="https://github.com/jemalloc/jemalloc.git"
|
||||
["nlohmann"]="https://raw.githubusercontent.com/nlohmann/json/4f8fba14066156b73f1189a2b8bd568bde5284c5/single_include/nlohmann/json.hpp"
|
||||
["neo4j"]="https://s3-eu-west-1.amazonaws.com/deps.memgraph.io/neo4j-community-3.2.3-unix.tar.gz"
|
||||
["librdkafka"]="https://github.com/edenhill/librdkafka.git"
|
||||
["protobuf"]="https://github.com/protocolbuffers/protobuf.git"
|
||||
["boost"]="https://boostorg.jfrog.io/artifactory/main/release/1.77.0/source/boost_1_77_0.tar.gz"
|
||||
["pulsar"]="https://github.com/apache/pulsar.git"
|
||||
["librdtsc"]="https://github.com/gabrieleara/librdtsc.git"
|
||||
)
|
||||
|
||||
# antlr
|
||||
@@ -209,8 +199,8 @@ git apply ../rocksdb.patch
|
||||
popd
|
||||
|
||||
# mgclient
|
||||
mgclient_tag="v1.3.0" # (2021-09-23)
|
||||
repo_clone_try_double "${primary_urls[mgclient]}" "${secondary_urls[mgclient]}" "mgclient" "$mgclient_tag" true
|
||||
mgclient_tag="96e95c6845463cbe88948392be58d26da0d5ffd3" # (2022-02-08)
|
||||
repo_clone_try_double "${primary_urls[mgclient]}" "${secondary_urls[mgclient]}" "mgclient" "$mgclient_tag"
|
||||
sed -i 's/\${CMAKE_INSTALL_LIBDIR}/lib/' mgclient/src/CMakeLists.txt
|
||||
|
||||
# pymgclient
|
||||
@@ -241,3 +231,10 @@ repo_clone_try_double "${primary_urls[pulsar]}" "${secondary_urls[pulsar]}" "pul
|
||||
pushd pulsar
|
||||
git apply ../pulsar.patch
|
||||
popd
|
||||
|
||||
#librdtsc
|
||||
librdtsc_tag="v0.3"
|
||||
repo_clone_try_double "${primary_urls[librdtsc]}" "${secondary_urls[librdtsc]}" "librdtsc" "$librdtsc_tag" true
|
||||
pushd librdtsc
|
||||
git apply ../librdtsc.patch
|
||||
popd
|
||||
|
||||
@@ -36,7 +36,7 @@ ADDITIONAL USE GRANT: You may use the Licensed Work in accordance with the
|
||||
3. using the Licensed Work to create a work or solution
|
||||
which competes (or might reasonably be expected to
|
||||
compete) with the Licensed Work.
|
||||
CHANGE DATE: 2025-12-08
|
||||
CHANGE DATE: 2026-27-04
|
||||
CHANGE LICENSE: Apache License, Version 2.0
|
||||
|
||||
For information about alternative licensing arrangements, please visit: https://memgraph.com/legal.
|
||||
|
||||
@@ -7,13 +7,11 @@ import copy
|
||||
|
||||
|
||||
@mgp.read_proc
|
||||
def procedure(context: mgp.ProcCtx,
|
||||
required_arg: mgp.Nullable[mgp.Any],
|
||||
optional_arg: mgp.Nullable[mgp.Any] = None
|
||||
) -> mgp.Record(args=list,
|
||||
vertex_count=int,
|
||||
avg_degree=mgp.Number,
|
||||
props=mgp.Nullable[mgp.Map]):
|
||||
def procedure(
|
||||
context: mgp.ProcCtx,
|
||||
required_arg: mgp.Nullable[mgp.Any],
|
||||
optional_arg: mgp.Nullable[mgp.Any] = None,
|
||||
) -> mgp.Record(args=list, vertex_count=int, avg_degree=mgp.Number, props=mgp.Nullable[mgp.Map]):
|
||||
"""
|
||||
This example procedure returns 4 fields.
|
||||
|
||||
@@ -37,7 +35,7 @@ def procedure(context: mgp.ProcCtx,
|
||||
if isinstance(required_arg, (mgp.Edge, mgp.Vertex)):
|
||||
props = dict(required_arg.properties.items())
|
||||
elif isinstance(required_arg, mgp.Path):
|
||||
start_vertex, = required_arg.vertices
|
||||
(start_vertex,) = required_arg.vertices
|
||||
props = dict(start_vertex.properties.items())
|
||||
# Count the vertices and edges in the database; this may take a while.
|
||||
vertex_count = 0
|
||||
@@ -51,15 +49,13 @@ def procedure(context: mgp.ProcCtx,
|
||||
# Copy the received arguments to make it equivalent to the C example.
|
||||
args_copy = [copy.deepcopy(required_arg), copy.deepcopy(optional_arg)]
|
||||
# Multiple rows can be produced by returning an iterable of mgp.Record.
|
||||
return mgp.Record(args=args_copy, vertex_count=vertex_count,
|
||||
avg_degree=avg_degree, props=props)
|
||||
return mgp.Record(args=args_copy, vertex_count=vertex_count, avg_degree=avg_degree, props=props)
|
||||
|
||||
|
||||
@mgp.write_proc
|
||||
def write_procedure(context: mgp.ProcCtx,
|
||||
property_name: str,
|
||||
property_value: mgp.Nullable[mgp.Any]
|
||||
) -> mgp.Record(created_vertex=mgp.Vertex):
|
||||
def write_procedure(
|
||||
context: mgp.ProcCtx, property_name: str, property_value: mgp.Nullable[mgp.Any]
|
||||
) -> mgp.Record(created_vertex=mgp.Vertex):
|
||||
"""
|
||||
This example procedure creates a new vertex with the specified property
|
||||
and connects it to all existing vertex which has the same property with
|
||||
|
||||
@@ -4,15 +4,17 @@ from collections import OrderedDict
|
||||
from itertools import chain, repeat
|
||||
from inspect import cleandoc
|
||||
from typing import List, Tuple
|
||||
|
||||
try:
|
||||
import networkx as nx
|
||||
except ImportError as import_error:
|
||||
sys.stderr.write((
|
||||
'\n'
|
||||
'NOTE: Please install networkx to be able to use graph_analyzer '
|
||||
'module. Using Python:\n'
|
||||
+ sys.version +
|
||||
'\n'))
|
||||
sys.stderr.write(
|
||||
(
|
||||
"\n"
|
||||
"NOTE: Please install networkx to be able to use graph_analyzer "
|
||||
"module. Using Python:\n" + sys.version + "\n"
|
||||
)
|
||||
)
|
||||
raise import_error
|
||||
# Imported last because it also depends on networkx.
|
||||
from mgp_networkx import MemgraphMultiDiGraph # noqa E402
|
||||
@@ -23,16 +25,14 @@ _MAX_LIST_SIZE = 10
|
||||
|
||||
@mgp.read_proc
|
||||
def help() -> mgp.Record(name=str, value=str):
|
||||
'''Shows manual page for graph_analyzer.'''
|
||||
"""Shows manual page for graph_analyzer."""
|
||||
records = []
|
||||
|
||||
def make_records(name, doc):
|
||||
return (mgp.Record(name=n, value=v) for n, v in
|
||||
zip(chain([name], repeat('')), cleandoc(doc).splitlines()))
|
||||
return (mgp.Record(name=n, value=v) for n, v in zip(chain([name], repeat("")), cleandoc(doc).splitlines()))
|
||||
|
||||
for func in (help, analyze, analyze_subgraph):
|
||||
records.extend(make_records("Procedure '{}'".format(func.__name__),
|
||||
func.__doc__))
|
||||
records.extend(make_records("Procedure '{}'".format(func.__name__), func.__doc__))
|
||||
|
||||
for m, v in _get_analysis_mapping().items():
|
||||
records.extend(make_records("Analysis '{}'".format(m), v.__doc__))
|
||||
@@ -41,10 +41,8 @@ def help() -> mgp.Record(name=str, value=str):
|
||||
|
||||
|
||||
@mgp.read_proc
|
||||
def analyze(context: mgp.ProcCtx,
|
||||
analyses: mgp.Nullable[List[str]] = None
|
||||
) -> mgp.Record(name=str, value=str):
|
||||
'''
|
||||
def analyze(context: mgp.ProcCtx, analyses: mgp.Nullable[List[str]] = None) -> mgp.Record(name=str, value=str):
|
||||
"""
|
||||
Shows graph information.
|
||||
|
||||
In case of multiple results, only the first 10 will be shown.
|
||||
@@ -57,19 +55,20 @@ def analyze(context: mgp.ProcCtx,
|
||||
|
||||
Example call (with parameter):
|
||||
CALL graph_analyzer.analyze(['nodes', 'edges']) YIELD *;
|
||||
'''
|
||||
"""
|
||||
g = MemgraphMultiDiGraph(ctx=context)
|
||||
recs = _analyze_graph(context, g, analyses)
|
||||
return [mgp.Record(name=name, value=value) for name, value in recs]
|
||||
|
||||
|
||||
@mgp.read_proc
|
||||
def analyze_subgraph(context: mgp.ProcCtx,
|
||||
vertices: mgp.List[mgp.Vertex],
|
||||
edges: mgp.List[mgp.Edge],
|
||||
analyses: mgp.Nullable[List[str]] = None
|
||||
) -> mgp.Record(name=str, value=str):
|
||||
'''
|
||||
def analyze_subgraph(
|
||||
context: mgp.ProcCtx,
|
||||
vertices: mgp.List[mgp.Vertex],
|
||||
edges: mgp.List[mgp.Edge],
|
||||
analyses: mgp.Nullable[List[str]] = None,
|
||||
) -> mgp.Record(name=str, value=str):
|
||||
"""
|
||||
Shows subgraph information.
|
||||
|
||||
In case of multiple results, only the first 10 will be shown.
|
||||
@@ -91,36 +90,40 @@ def analyze_subgraph(context: mgp.ProcCtx,
|
||||
CALL graph_analyzer.analyze_subgraph(nodes, edges, ['nodes', 'edges'])
|
||||
YIELD *
|
||||
RETURN name, value;
|
||||
'''
|
||||
"""
|
||||
vertices, edges = map(set, [vertices, edges])
|
||||
g = nx.subgraph_view(
|
||||
MemgraphMultiDiGraph(ctx=context),
|
||||
lambda n: n in vertices,
|
||||
lambda n1, n2, e: e in edges)
|
||||
lambda n1, n2, e: e in edges,
|
||||
)
|
||||
recs = _analyze_graph(context, g, analyses)
|
||||
return [mgp.Record(name=name, value=value) for name, value in recs]
|
||||
|
||||
|
||||
def _get_analysis_mapping():
|
||||
return OrderedDict([
|
||||
('nodes', _number_of_nodes),
|
||||
('edges', _number_of_edges),
|
||||
('bridges', _bridges),
|
||||
('articulation_points', _articulation_points),
|
||||
('avg_degree', _avg_degree),
|
||||
('sorted_nodes_degree', _sorted_nodes_degree),
|
||||
('self_loops', _self_loops),
|
||||
('is_bipartite', _is_bipartite),
|
||||
('is_planar', _is_planar),
|
||||
('is_biconnected: ', _is_biconnected),
|
||||
('is_weakly_connected', _is_weakly_connected),
|
||||
('number_of_weakly_components', _weakly_components),
|
||||
('is_strongly_connected', _is_strongly_connected),
|
||||
('strongly_components', _strongly_components),
|
||||
('is_dag', _is_dag),
|
||||
('is_eulerian', _is_eulerian),
|
||||
('is_forest', _is_forest),
|
||||
('is_tree', _is_tree)])
|
||||
return OrderedDict(
|
||||
[
|
||||
("nodes", _number_of_nodes),
|
||||
("edges", _number_of_edges),
|
||||
("bridges", _bridges),
|
||||
("articulation_points", _articulation_points),
|
||||
("avg_degree", _avg_degree),
|
||||
("sorted_nodes_degree", _sorted_nodes_degree),
|
||||
("self_loops", _self_loops),
|
||||
("is_bipartite", _is_bipartite),
|
||||
("is_planar", _is_planar),
|
||||
("is_biconnected: ", _is_biconnected),
|
||||
("is_weakly_connected", _is_weakly_connected),
|
||||
("number_of_weakly_components", _weakly_components),
|
||||
("is_strongly_connected", _is_strongly_connected),
|
||||
("strongly_components", _strongly_components),
|
||||
("is_dag", _is_dag),
|
||||
("is_eulerian", _is_eulerian),
|
||||
("is_forest", _is_forest),
|
||||
("is_tree", _is_tree),
|
||||
]
|
||||
)
|
||||
|
||||
|
||||
def _get_analysis_func(name: str):
|
||||
@@ -132,20 +135,15 @@ def _get_analysis_funcs():
|
||||
return _get_analysis_mapping().values()
|
||||
|
||||
|
||||
def _analyze_graph(context: mgp.ProcCtx,
|
||||
g: nx.MultiDiGraph,
|
||||
analyses: List[str]
|
||||
) -> List[Tuple[str, str]]:
|
||||
def _analyze_graph(context: mgp.ProcCtx, g: nx.MultiDiGraph, analyses: List[str]) -> List[Tuple[str, str]]:
|
||||
|
||||
functions = (_get_analysis_funcs() if analyses is None
|
||||
else [_get_analysis_func(name) for name in analyses])
|
||||
functions = _get_analysis_funcs() if analyses is None else [_get_analysis_func(name) for name in analyses]
|
||||
|
||||
records = []
|
||||
for index, f in enumerate(functions):
|
||||
context.check_must_abort()
|
||||
if f is None:
|
||||
raise KeyError('Graph analysis is not supported: ' +
|
||||
analyses[index])
|
||||
raise KeyError("Graph analysis is not supported: " + analyses[index])
|
||||
name, value = f(g)
|
||||
if isinstance(value, (list, set, tuple)):
|
||||
value = list(value)[:_MAX_LIST_SIZE]
|
||||
@@ -155,126 +153,120 @@ def _analyze_graph(context: mgp.ProcCtx,
|
||||
|
||||
|
||||
def _number_of_nodes(g: nx.MultiDiGraph) -> Tuple[str, int]:
|
||||
'''Returns number of nodes.'''
|
||||
return 'Number of nodes', nx.number_of_nodes(g)
|
||||
"""Returns number of nodes."""
|
||||
return "Number of nodes", nx.number_of_nodes(g)
|
||||
|
||||
|
||||
def _number_of_edges(g: nx.MultiDiGraph) -> Tuple[str, int]:
|
||||
'''Returns number of edges.'''
|
||||
return 'Number of edges', nx.number_of_edges(g)
|
||||
"""Returns number of edges."""
|
||||
return "Number of edges", nx.number_of_edges(g)
|
||||
|
||||
|
||||
def _avg_degree(g: nx.MultiDiGraph) -> Tuple[str, float]:
|
||||
'''Returns average degree.'''
|
||||
"""Returns average degree."""
|
||||
_, number_of_nodes = _number_of_nodes(g)
|
||||
_, number_of_edges = _number_of_edges(g)
|
||||
avg_degree = (0 if number_of_nodes == 0
|
||||
else number_of_edges / number_of_nodes)
|
||||
return 'Average degree', avg_degree
|
||||
avg_degree = 0 if number_of_nodes == 0 else number_of_edges / number_of_nodes
|
||||
return "Average degree", avg_degree
|
||||
|
||||
|
||||
def _sorted_nodes_degree(g: nx.MultiDiGraph) -> Tuple[str, List[int]]:
|
||||
'''Returns list of sorted nodes degree. [(node_id, degree), ...]'''
|
||||
"""Returns list of sorted nodes degree. [(node_id, degree), ...]"""
|
||||
nodes_degree = [(n, g.degree(n)) for n in g.nodes()]
|
||||
nodes_degree.sort(key=lambda x: x[1], reverse=True)
|
||||
return 'Sorted nodes degree', nodes_degree
|
||||
return "Sorted nodes degree", nodes_degree
|
||||
|
||||
|
||||
def _self_loops(g: nx.MultiDiGraph) -> Tuple[str, int]:
|
||||
'''Returns number of self loops.'''
|
||||
return 'Self loops', sum((1 if e[0] == e[1] else 0 for e in g.edges()))
|
||||
"""Returns number of self loops."""
|
||||
return "Self loops", sum((1 if e[0] == e[1] else 0 for e in g.edges()))
|
||||
|
||||
|
||||
def _is_bipartite(g: nx.MultiDiGraph) -> Tuple[str, bool]:
|
||||
'''Checks if graph is bipartite.'''
|
||||
"""Checks if graph is bipartite."""
|
||||
_, number_of_nodes = _number_of_nodes(g)
|
||||
ret = (False if number_of_nodes == 0
|
||||
else nx.algorithms.bipartite.basic.is_bipartite(g))
|
||||
return 'Is bipartite', ret
|
||||
ret = False if number_of_nodes == 0 else nx.algorithms.bipartite.basic.is_bipartite(g)
|
||||
return "Is bipartite", ret
|
||||
|
||||
|
||||
def _is_planar(g: nx.MultiDiGraph) -> Tuple[str, bool]:
|
||||
'''Checks if graph is planar.'''
|
||||
"""Checks if graph is planar."""
|
||||
_, number_of_nodes = _number_of_nodes(g)
|
||||
ret = (False if number_of_nodes == 0
|
||||
else nx.algorithms.planarity.check_planarity(g)[0])
|
||||
return 'Is planar', ret
|
||||
ret = False if number_of_nodes == 0 else nx.algorithms.planarity.check_planarity(g)[0]
|
||||
return "Is planar", ret
|
||||
|
||||
|
||||
def _is_biconnected(g: nx.MultiDiGraph) -> Tuple[str, bool]:
|
||||
'''Check if graph is biconnected.'''
|
||||
"""Check if graph is biconnected."""
|
||||
_, number_of_nodes = _number_of_nodes(g)
|
||||
ret = (False if number_of_nodes == 0
|
||||
else nx.is_biconnected(nx.MultiDiGraph.to_undirected(g)))
|
||||
return 'Is biconnected', ret
|
||||
ret = False if number_of_nodes == 0 else nx.is_biconnected(nx.MultiDiGraph.to_undirected(g))
|
||||
return "Is biconnected", ret
|
||||
|
||||
|
||||
def _is_weakly_connected(g: nx.MultiDiGraph) -> Tuple[str, bool]:
|
||||
'''Check if graph is weakly connected.'''
|
||||
"""Check if graph is weakly connected."""
|
||||
_, number_of_nodes = _number_of_nodes(g)
|
||||
ret = False if number_of_nodes == 0 else nx.is_weakly_connected(g)
|
||||
return 'Is weakly connected', ret
|
||||
return "Is weakly connected", ret
|
||||
|
||||
|
||||
def _is_strongly_connected(g: nx.MultiDiGraph) -> Tuple[str, bool]:
|
||||
'''Checks if graph is strongly connected.'''
|
||||
"""Checks if graph is strongly connected."""
|
||||
_, number_of_nodes = _number_of_nodes(g)
|
||||
ret = False if number_of_nodes == 0 else nx.is_strongly_connected(g)
|
||||
return 'Is strongly connected', ret
|
||||
return "Is strongly connected", ret
|
||||
|
||||
|
||||
def _is_dag(g: nx.MultiDiGraph) -> Tuple[str, bool]:
|
||||
'''Check if graph is directed acyclic graph (DAG)'''
|
||||
"""Check if graph is directed acyclic graph (DAG)"""
|
||||
_, number_of_nodes = _number_of_nodes(g)
|
||||
ret = (False if number_of_nodes == 0
|
||||
else nx.algorithms.dag.is_directed_acyclic_graph(g))
|
||||
return 'Is DAG', ret
|
||||
ret = False if number_of_nodes == 0 else nx.algorithms.dag.is_directed_acyclic_graph(g)
|
||||
return "Is DAG", ret
|
||||
|
||||
|
||||
def _is_eulerian(g: nx.MultiDiGraph) -> Tuple[str, bool]:
|
||||
'''Checks if graph is Eulerian.'''
|
||||
"""Checks if graph is Eulerian."""
|
||||
_, number_of_nodes = _number_of_nodes(g)
|
||||
ret = (False if number_of_nodes == 0
|
||||
else nx.algorithms.euler.is_eulerian(g))
|
||||
return 'Is eulerian', ret
|
||||
ret = False if number_of_nodes == 0 else nx.algorithms.euler.is_eulerian(g)
|
||||
return "Is eulerian", ret
|
||||
|
||||
|
||||
def _is_forest(g: nx.MultiDiGraph) -> Tuple[str, bool]:
|
||||
'''Checks if graph is forest, all components must be trees.'''
|
||||
"""Checks if graph is forest, all components must be trees."""
|
||||
_, number_of_nodes = _number_of_nodes(g)
|
||||
ret = (False if number_of_nodes == 0
|
||||
else nx.algorithms.tree.recognition.is_forest(g))
|
||||
return 'Is forest', ret
|
||||
ret = False if number_of_nodes == 0 else nx.algorithms.tree.recognition.is_forest(g)
|
||||
return "Is forest", ret
|
||||
|
||||
|
||||
def _is_tree(g: nx.MultiDiGraph) -> Tuple[str, bool]:
|
||||
'''Checks if graph is tree.'''
|
||||
"""Checks if graph is tree."""
|
||||
_, number_of_nodes = _number_of_nodes(g)
|
||||
ret = (False if number_of_nodes == 0
|
||||
else nx.algorithms.tree.recognition.is_tree(g))
|
||||
return 'Is tree', ret
|
||||
ret = False if number_of_nodes == 0 else nx.algorithms.tree.recognition.is_tree(g)
|
||||
return "Is tree", ret
|
||||
|
||||
|
||||
def _bridges(g: nx.MultiDiGraph) -> Tuple[str, int]:
|
||||
'''Returns number of bridges, multiple edges between same nodes are
|
||||
mapped to one edge.'''
|
||||
return 'Number of bridges', sum(1 for _ in nx.bridges(nx.Graph(g)))
|
||||
"""Returns number of bridges, multiple edges between same nodes are
|
||||
mapped to one edge."""
|
||||
return "Number of bridges", sum(1 for _ in nx.bridges(nx.Graph(g)))
|
||||
|
||||
|
||||
def _articulation_points(g: nx.MultiDiGraph):
|
||||
'''Returns number of articulation points.'''
|
||||
"""Returns number of articulation points."""
|
||||
undirected = nx.MultiDiGraph.to_undirected(g)
|
||||
return ('Number of articulation points',
|
||||
sum(1 for _ in nx.articulation_points(undirected)))
|
||||
return (
|
||||
"Number of articulation points",
|
||||
sum(1 for _ in nx.articulation_points(undirected)),
|
||||
)
|
||||
|
||||
|
||||
def _weakly_components(g: nx.MultiDiGraph):
|
||||
'''Returns number of weakly components.'''
|
||||
"""Returns number of weakly components."""
|
||||
comps = nx.algorithms.components.number_weakly_connected_components(g)
|
||||
return 'Number of weakly connected components', comps
|
||||
return "Number of weakly connected components", comps
|
||||
|
||||
|
||||
def _strongly_components(g: nx.MultiDiGraph):
|
||||
'''Returns number of strongly connected components.'''
|
||||
"""Returns number of strongly connected components."""
|
||||
comps = nx.algorithms.components.number_strongly_connected_components(g)
|
||||
return 'Number of strongly connected components', comps
|
||||
return "Number of strongly connected components", comps
|
||||
|
||||
@@ -1,20 +1,22 @@
|
||||
import sys
|
||||
import mgp
|
||||
import collections
|
||||
|
||||
try:
|
||||
import networkx as nx
|
||||
except ImportError as import_error:
|
||||
sys.stderr.write((
|
||||
'\n'
|
||||
'NOTE: Please install networkx to be able to use Memgraph NetworkX '
|
||||
'wrappers. Using Python:\n'
|
||||
+ sys.version +
|
||||
'\n'))
|
||||
sys.stderr.write(
|
||||
(
|
||||
"\n"
|
||||
"NOTE: Please install networkx to be able to use Memgraph NetworkX "
|
||||
"wrappers. Using Python:\n" + sys.version + "\n"
|
||||
)
|
||||
)
|
||||
raise import_error
|
||||
|
||||
|
||||
class MemgraphAdjlistOuterDict(collections.abc.Mapping):
|
||||
__slots__ = ('_ctx', '_succ', '_multi')
|
||||
__slots__ = ("_ctx", "_succ", "_multi")
|
||||
|
||||
def __init__(self, ctx, succ=True, multi=True):
|
||||
self._ctx = ctx
|
||||
@@ -24,8 +26,7 @@ class MemgraphAdjlistOuterDict(collections.abc.Mapping):
|
||||
def __getitem__(self, key):
|
||||
if key not in self:
|
||||
raise KeyError
|
||||
return MemgraphAdjlistInnerDict(key, succ=self._succ,
|
||||
multi=self._multi)
|
||||
return MemgraphAdjlistInnerDict(key, succ=self._succ, multi=self._multi)
|
||||
|
||||
def __iter__(self):
|
||||
return iter(self._ctx.graph.vertices)
|
||||
@@ -40,7 +41,7 @@ class MemgraphAdjlistOuterDict(collections.abc.Mapping):
|
||||
|
||||
|
||||
class MemgraphAdjlistInnerDict(collections.abc.Mapping):
|
||||
__slots__ = ('_node', '_succ', '_multi', '_neighbors')
|
||||
__slots__ = ("_node", "_succ", "_multi", "_neighbors")
|
||||
|
||||
def __init__(self, node, succ=True, multi=True):
|
||||
self._node = node
|
||||
@@ -71,31 +72,26 @@ class MemgraphAdjlistInnerDict(collections.abc.Mapping):
|
||||
def _get_neighbors(self):
|
||||
if not self._neighbors:
|
||||
if self._succ:
|
||||
self._neighbors = set(
|
||||
e.to_vertex for e in self._node.out_edges)
|
||||
self._neighbors = set(e.to_vertex for e in self._node.out_edges)
|
||||
else:
|
||||
self._neighbors = set(
|
||||
e.from_vertex for e in self._node.in_edges)
|
||||
self._neighbors = set(e.from_vertex for e in self._node.in_edges)
|
||||
return self._neighbors
|
||||
|
||||
def _get_edge(self, neighbor):
|
||||
if self._succ:
|
||||
edge = list(filter(lambda e: e.to_vertex == neighbor,
|
||||
self._node.out_edges))
|
||||
edge = list(filter(lambda e: e.to_vertex == neighbor, self._node.out_edges))
|
||||
else:
|
||||
edge = list(filter(lambda e: e.from_vertex == neighbor,
|
||||
self._node.in_edges))
|
||||
edge = list(filter(lambda e: e.from_vertex == neighbor, self._node.in_edges))
|
||||
|
||||
assert len(edge) >= 1
|
||||
if len(edge) > 1:
|
||||
raise RuntimeError('Graph contains multiedges but '
|
||||
'is of non-multigraph type: {}'.format(edge))
|
||||
raise RuntimeError("Graph contains multiedges but " "is of non-multigraph type: {}".format(edge))
|
||||
|
||||
return edge[0]
|
||||
|
||||
|
||||
class MemgraphEdgeKeyDict(collections.abc.Mapping):
|
||||
__slots__ = ('_node', '_neighbor', '_succ', '_edges')
|
||||
__slots__ = ("_node", "_neighbor", "_succ", "_edges")
|
||||
|
||||
def __init__(self, node, neighbor, succ=True):
|
||||
self._node = node
|
||||
@@ -122,18 +118,14 @@ class MemgraphEdgeKeyDict(collections.abc.Mapping):
|
||||
def _get_edges(self):
|
||||
if not self._edges:
|
||||
if self._succ:
|
||||
self._edges = list(filter(
|
||||
lambda e: e.to_vertex == self._neighbor,
|
||||
self._node.out_edges))
|
||||
self._edges = list(filter(lambda e: e.to_vertex == self._neighbor, self._node.out_edges))
|
||||
else:
|
||||
self._edges = list(filter(
|
||||
lambda e: e.from_vertex == self._neighbor,
|
||||
self._node.in_edges))
|
||||
self._edges = list(filter(lambda e: e.from_vertex == self._neighbor, self._node.in_edges))
|
||||
return self._edges
|
||||
|
||||
|
||||
class UnhashableProperties(collections.abc.Mapping):
|
||||
__slots__ = ('_properties')
|
||||
__slots__ = "_properties"
|
||||
|
||||
def __init__(self, properties):
|
||||
self._properties = properties
|
||||
@@ -155,7 +147,7 @@ class UnhashableProperties(collections.abc.Mapping):
|
||||
|
||||
|
||||
class MemgraphNodeDict(collections.abc.Mapping):
|
||||
__slots__ = ('_ctx',)
|
||||
__slots__ = ("_ctx",)
|
||||
|
||||
def __init__(self, ctx):
|
||||
self._ctx = ctx
|
||||
@@ -187,8 +179,7 @@ class MemgraphNodeDict(collections.abc.Mapping):
|
||||
|
||||
|
||||
class MemgraphDiGraphBase:
|
||||
def __init__(self, incoming_graph_data=None, ctx=None, multi=True,
|
||||
**kwargs):
|
||||
def __init__(self, incoming_graph_data=None, ctx=None, multi=True, **kwargs):
|
||||
# NOTE: We assume that our graph will never be given any initial data
|
||||
# because we already pull our data from the Memgraph database. This
|
||||
# assert is triggered by certain NetworkX procedures because they
|
||||
@@ -201,23 +192,30 @@ class MemgraphDiGraphBase:
|
||||
# modify the graph's internal attributes and don't try to populate it
|
||||
# with initial data or modify it.
|
||||
|
||||
self.node_dict_factory = lambda: MemgraphNodeDict(ctx) \
|
||||
if ctx else self._error
|
||||
self.node_dict_factory = lambda: MemgraphNodeDict(ctx) if ctx else self._error
|
||||
self.node_attr_dict_factory = self._error
|
||||
|
||||
self.adjlist_outer_dict_factory = \
|
||||
lambda: MemgraphAdjlistOuterDict(ctx, multi=multi) \
|
||||
if ctx else self._error
|
||||
self.adjlist_outer_dict_factory = lambda: MemgraphAdjlistOuterDict(ctx, multi=multi) if ctx else self._error
|
||||
self.adjlist_inner_dict_factory = self._error
|
||||
self.edge_key_dict_factory = self._error
|
||||
self.edge_attr_dict_factory = self._error
|
||||
|
||||
# NOTE: We forbid any mutating operations because our graph is
|
||||
# immutable and pulls its data from the Memgraph database.
|
||||
for f in ['add_node', 'add_nodes_from', 'remove_node',
|
||||
'remove_nodes_from', 'add_edge', 'add_edges_from',
|
||||
'add_weighted_edges_from', 'new_edge_key', 'remove_edge',
|
||||
'remove_edges_from', 'update', 'clear']:
|
||||
for f in [
|
||||
"add_node",
|
||||
"add_nodes_from",
|
||||
"remove_node",
|
||||
"remove_nodes_from",
|
||||
"add_edge",
|
||||
"add_edges_from",
|
||||
"add_weighted_edges_from",
|
||||
"new_edge_key",
|
||||
"remove_edge",
|
||||
"remove_edges_from",
|
||||
"update",
|
||||
"clear",
|
||||
]:
|
||||
setattr(self, f, lambda *args, **kwargs: self._error())
|
||||
|
||||
super().__init__(None, **kwargs)
|
||||
@@ -231,33 +229,29 @@ class MemgraphDiGraphBase:
|
||||
self._pred = MemgraphAdjlistOuterDict(ctx, succ=False, multi=multi)
|
||||
|
||||
def _error(self):
|
||||
raise RuntimeError('Modification operations are not supported')
|
||||
raise RuntimeError("Modification operations are not supported")
|
||||
|
||||
|
||||
class MemgraphMultiDiGraph(MemgraphDiGraphBase, nx.MultiDiGraph):
|
||||
def __init__(self, incoming_graph_data=None, ctx=None, **kwargs):
|
||||
super().__init__(incoming_graph_data=incoming_graph_data,
|
||||
ctx=ctx, multi=True, **kwargs)
|
||||
super().__init__(incoming_graph_data=incoming_graph_data, ctx=ctx, multi=True, **kwargs)
|
||||
|
||||
|
||||
def MemgraphMultiGraph(incoming_graph_data=None, ctx=None, **kwargs):
|
||||
return MemgraphMultiDiGraph(incoming_graph_data=incoming_graph_data,
|
||||
ctx=ctx, **kwargs).to_undirected(as_view=True)
|
||||
return MemgraphMultiDiGraph(incoming_graph_data=incoming_graph_data, ctx=ctx, **kwargs).to_undirected(as_view=True)
|
||||
|
||||
|
||||
class MemgraphDiGraph(MemgraphDiGraphBase, nx.DiGraph):
|
||||
def __init__(self, incoming_graph_data=None, ctx=None, **kwargs):
|
||||
super().__init__(incoming_graph_data=incoming_graph_data,
|
||||
ctx=ctx, multi=False, **kwargs)
|
||||
super().__init__(incoming_graph_data=incoming_graph_data, ctx=ctx, multi=False, **kwargs)
|
||||
|
||||
|
||||
def MemgraphGraph(incoming_graph_data=None, ctx=None, **kwargs):
|
||||
return MemgraphDiGraph(incoming_graph_data=incoming_graph_data,
|
||||
ctx=ctx, **kwargs).to_undirected(as_view=True)
|
||||
return MemgraphDiGraph(incoming_graph_data=incoming_graph_data, ctx=ctx, **kwargs).to_undirected(as_view=True)
|
||||
|
||||
|
||||
class PropertiesDictionary(collections.abc.Mapping):
|
||||
__slots__ = ('_ctx', '_prop', '_len')
|
||||
__slots__ = ("_ctx", "_prop", "_len")
|
||||
|
||||
def __init__(self, ctx, prop):
|
||||
self._ctx = ctx
|
||||
@@ -270,8 +264,7 @@ class PropertiesDictionary(collections.abc.Mapping):
|
||||
try:
|
||||
return vertex.properties[self._prop]
|
||||
except KeyError:
|
||||
raise KeyError(("{} doesn\t have the required " +
|
||||
"property '{}'").format(vertex, self._prop))
|
||||
raise KeyError(("{} doesn\t have the required " + "property '{}'").format(vertex, self._prop))
|
||||
|
||||
def __iter__(self):
|
||||
for v in self._ctx.graph.vertices:
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -1,23 +1,20 @@
|
||||
import sys
|
||||
import mgp
|
||||
|
||||
try:
|
||||
import networkx as nx
|
||||
except ImportError as import_error:
|
||||
sys.stderr.write(
|
||||
'\n'
|
||||
'NOTE: Please install networkx to be able to use wcc module.\n'
|
||||
'Using Python:\n'
|
||||
+ sys.version +
|
||||
'\n')
|
||||
"\n" "NOTE: Please install networkx to be able to use wcc module.\n" "Using Python:\n" + sys.version + "\n"
|
||||
)
|
||||
raise import_error
|
||||
|
||||
|
||||
@mgp.read_proc
|
||||
def get_components(vertices: mgp.List[mgp.Vertex],
|
||||
edges: mgp.List[mgp.Edge]
|
||||
) -> mgp.Record(n_components=int,
|
||||
components=mgp.List[mgp.List[mgp.Vertex]]):
|
||||
'''
|
||||
def get_components(
|
||||
vertices: mgp.List[mgp.Vertex], edges: mgp.List[mgp.Edge]
|
||||
) -> mgp.Record(n_components=int, components=mgp.List[mgp.List[mgp.Vertex]]):
|
||||
"""
|
||||
This procedure finds weakly connected components of a given subgraph of a
|
||||
directed graph.
|
||||
|
||||
@@ -41,7 +38,7 @@ def get_components(vertices: mgp.List[mgp.Vertex],
|
||||
WITH collect(n) AS nodes, collect(e) AS edges
|
||||
CALL wcc.get_components(nodes, edges) YIELD *
|
||||
RETURN n_components, components;
|
||||
'''
|
||||
"""
|
||||
g = nx.DiGraph()
|
||||
g.add_nodes_from(vertices)
|
||||
g.add_edges_from([(edge.from_vertex, edge.to_vertex) for edge in edges])
|
||||
|
||||
@@ -10,6 +10,14 @@ set(CPACK_PACKAGE_VENDOR "Memgraph Ltd.")
|
||||
set(CPACK_PACKAGE_DESCRIPTION_SUMMARY
|
||||
"High performance, in-memory, transactional graph database")
|
||||
|
||||
# Setting arhitecture extension for deb packages
|
||||
set(MG_ARCH_EXTENSION_DEB "all")
|
||||
if (${MG_ARCH} STREQUAL "x86_64")
|
||||
set(MG_ARCH_EXTENSION_DEB "amd64")
|
||||
elseif (${MG_ARCH} STREQUAL "ARM64")
|
||||
set(MG_ARCH_EXTENSION_DEB "arm64")
|
||||
endif()
|
||||
|
||||
# DEB specific
|
||||
# Instead of using "name <email>" format, we use "email (name)" to prevent
|
||||
# errors due to full stop, '.' at the end of "Ltd". (See: RFC 822)
|
||||
@@ -17,7 +25,7 @@ set(CPACK_DEBIAN_PACKAGE_MAINTAINER "tech@memgraph.com (Memgraph Ltd.)")
|
||||
set(CPACK_DEBIAN_PACKAGE_SECTION non-free/database)
|
||||
set(CPACK_DEBIAN_PACKAGE_HOMEPAGE https://memgraph.com)
|
||||
set(CPACK_DEBIAN_PACKAGE_VERSION "${MEMGRAPH_VERSION_DEB}")
|
||||
set(CPACK_DEBIAN_FILE_NAME "memgraph_${MEMGRAPH_VERSION_DEB}_amd64.deb")
|
||||
set(CPACK_DEBIAN_FILE_NAME "memgraph_${MEMGRAPH_VERSION_DEB}_${MG_ARCH_EXTENSION_DEB}.deb")
|
||||
set(CPACK_DEBIAN_PACKAGE_CONTROL_EXTRA
|
||||
"${CMAKE_CURRENT_SOURCE_DIR}/debian/conffiles;"
|
||||
"${CMAKE_CURRENT_SOURCE_DIR}/debian/copyright;"
|
||||
@@ -33,12 +41,20 @@ set(CPACK_DEBIAN_PACKAGE_DESCRIPTION "${CPACK_PACKAGE_DESCRIPTION_SUMMARY}
|
||||
applications driver by real-time connected data.")
|
||||
# Add `openssl` package to dependencies list. Used to generate SSL certificates.
|
||||
# We also depend on `python3` because we embed it in Memgraph.
|
||||
set(CPACK_DEBIAN_PACKAGE_DEPENDS "openssl (>= 1.1.0), python3 (>= 3.5.0)")
|
||||
set(CPACK_DEBIAN_PACKAGE_DEPENDS "openssl (>= 1.1.0), python3 (>= 3.5.0), libstdc++6")
|
||||
|
||||
# Setting arhitecture extension for rpm packages
|
||||
set(MG_ARCH_EXTENSION_RPM "noarch")
|
||||
if (${MG_ARCH} STREQUAL "x86_64")
|
||||
set(MG_ARCH_EXTENSION_RPM "x86_64")
|
||||
elseif (${MG_ARCH} STREQUAL "ARM64")
|
||||
set(MG_ARCH_EXTENSION_RPM "aarch64")
|
||||
endif()
|
||||
|
||||
# RPM specific
|
||||
set(CPACK_RPM_PACKAGE_URL https://memgraph.com)
|
||||
set(CPACK_RPM_PACKAGE_VERSION "${MEMGRAPH_VERSION_RPM}")
|
||||
set(CPACK_RPM_FILE_NAME "memgraph-${MEMGRAPH_VERSION_RPM}-1.x86_64.rpm")
|
||||
set(CPACK_RPM_FILE_NAME "memgraph-${MEMGRAPH_VERSION_RPM}-1.${MG_ARCH_EXTENSION_RPM}.rpm")
|
||||
set(CPACK_RPM_EXCLUDE_FROM_AUTO_FILELIST_ADDITION
|
||||
/var /var/lib /var/log /etc/logrotate.d
|
||||
/lib /lib/systemd /lib/systemd/system /lib/systemd/system/memgraph.service)
|
||||
@@ -51,7 +67,7 @@ It aims to deliver developers the speed, simplicity and scale required to build
|
||||
the next generation of applications driver by real-time connected data.")
|
||||
# Add `openssl` package to dependencies list. Used to generate SSL certificates.
|
||||
# We also depend on `python3` because we embed it in Memgraph.
|
||||
set(CPACK_RPM_PACKAGE_REQUIRES "openssl >= 1.0.0, curl >= 7.29.0, python3 >= 3.5.0")
|
||||
set(CPACK_RPM_PACKAGE_REQUIRES "openssl >= 1.0.0, curl >= 7.29.0, python3 >= 3.5.0, libstdc >= 6, logrotate")
|
||||
|
||||
# All variables must be set before including.
|
||||
include(CPack)
|
||||
|
||||
19
release/arm64/build_env.dockerfile
Normal file
19
release/arm64/build_env.dockerfile
Normal file
@@ -0,0 +1,19 @@
|
||||
FROM dokken/centos-stream-9
|
||||
|
||||
ARG env_folder
|
||||
ARG toolchain_version
|
||||
|
||||
COPY ${env_folder} /env_folder
|
||||
|
||||
RUN yum update && yum install -y curl git
|
||||
|
||||
RUN /${env_folder}/os/centos-9.sh install MEMGRAPH_BUILD_DEPS
|
||||
RUN /${env_folder}/os/centos-9.sh install TOOLCHAIN_RUN_DEPS
|
||||
|
||||
RUN rm -rf /env_folder
|
||||
|
||||
RUN yum clean all
|
||||
|
||||
RUN curl https://s3.eu-west-1.amazonaws.com/deps.memgraph.io/${toolchain_version}/${toolchain_version}-binaries-centos-9-arm64.tar.gz -o /tmp/toolchain.tar.gz \
|
||||
&& tar xvzf /tmp/toolchain.tar.gz -C /opt \
|
||||
&& rm /tmp/toolchain.tar.gz
|
||||
5
release/arm64/build_env.sh
Executable file
5
release/arm64/build_env.sh
Executable file
@@ -0,0 +1,5 @@
|
||||
#!/bin/bash
|
||||
|
||||
cp -r ../../environment env_folder
|
||||
docker build -f build_env.dockerfile --build-arg env_folder=env_folder --build-arg toolchain_version=toolchain-v4 -t mg_build_env .
|
||||
rm -rf env_folder
|
||||
@@ -1,19 +1,21 @@
|
||||
FROM debian:bullseye
|
||||
# NOTE: If you change the base distro update release/package as well.
|
||||
|
||||
ARG deb_release
|
||||
ARG BINARY_NAME
|
||||
ARG EXTENSION
|
||||
ARG TARGETARCH
|
||||
|
||||
RUN apt-get update && apt-get install -y \
|
||||
openssl libcurl4 libssl1.1 libseccomp2 python3 libpython3.9 python3-pip \
|
||||
--no-install-recommends \
|
||||
openssl libcurl4 libssl1.1 libseccomp2 python3 libpython3.9 python3-pip \
|
||||
--no-install-recommends \
|
||||
&& rm -rf /var/lib/apt/lists/* /tmp/* /var/tmp/*
|
||||
|
||||
RUN pip3 install networkx==2.4 numpy==1.21.4 scipy==1.7.3
|
||||
|
||||
COPY ${deb_release} /
|
||||
COPY "${BINARY_NAME}${TARGETARCH}.${EXTENSION}" /
|
||||
|
||||
# Install memgraph package
|
||||
RUN dpkg -i ${deb_release}
|
||||
RUN dpkg -i "${BINARY_NAME}${TARGETARCH}.deb"
|
||||
|
||||
# Memgraph listens for Bolt Protocol on this port by default.
|
||||
EXPOSE 7687
|
||||
@@ -1,46 +0,0 @@
|
||||
#!/bin/bash -e
|
||||
|
||||
# Build and package Docker image of Memgraph.
|
||||
|
||||
function print_help () {
|
||||
echo "Usage: $0 [--latest] MEMGRAPH_PACKAGE.deb"
|
||||
echo "Optional arguments:"
|
||||
echo -e "\t-h|--help\t\tPrint help."
|
||||
echo -e "\t--latest\t\tTag image as latest version."
|
||||
}
|
||||
|
||||
working_dir="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )"
|
||||
|
||||
latest_image=""
|
||||
tag_latest=""
|
||||
if [[ $# -eq 2 && "$1" == "--latest" ]]; then
|
||||
latest_image="memgraph:latest"
|
||||
tag_latest="-t memgraph:latest"
|
||||
shift
|
||||
elif [[ $# -ne 1 || "$1" == "-h" || "$1" == "--help" ]]; then
|
||||
print_help
|
||||
exit 1
|
||||
fi
|
||||
|
||||
deb_path="$1"
|
||||
if [[ ! -f "$deb_path" ]]; then
|
||||
echo "File '$deb_path' does not exist!"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# Copy the .deb to working directory.
|
||||
cp "$deb_path" "${working_dir}/"
|
||||
cd ${working_dir}
|
||||
|
||||
# Extract version and offering from deb name.
|
||||
deb_name=`echo $(basename "$deb_path") | sed 's/.deb$//'`
|
||||
version=`echo ${deb_name} | cut -d '_' -f 2 | rev | cut -d '-' -f 2- | rev | tr '+~' '__'`
|
||||
dockerfile_path="${working_dir}/memgraph.dockerfile"
|
||||
image_name="memgraph:${version}"
|
||||
package_name="memgraph-${version}-docker.tar.gz"
|
||||
|
||||
# Build docker image.
|
||||
docker build -t ${image_name} ${tag_latest} -f ${dockerfile_path} --build-arg deb_release=${deb_name}.deb .
|
||||
docker save ${image_name} ${latest_image} > ${package_name}
|
||||
rm "${deb_name}.deb"
|
||||
echo "Built Docker image at '${working_dir}/${package_name}'"
|
||||
64
release/docker/package_docker
Executable file
64
release/docker/package_docker
Executable file
@@ -0,0 +1,64 @@
|
||||
#!/bin/bash -e
|
||||
|
||||
# Build and package Docker image of Memgraph.
|
||||
|
||||
function print_help () {
|
||||
echo "Usage: $0 [--latest] MEMGRAPH_PACKAGE.(deb|rpm)"
|
||||
echo "Optional arguments:"
|
||||
echo -e "\t-h|--help\t\tPrint help."
|
||||
echo -e "\t--latest\t\tTag image as latest version."
|
||||
}
|
||||
|
||||
working_dir="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )"
|
||||
|
||||
latest_image=""
|
||||
tag_latest=""
|
||||
if [[ $# -eq 2 && "$1" == "--latest" ]]; then
|
||||
latest_image="memgraph:latest"
|
||||
tag_latest="-t memgraph:latest"
|
||||
shift
|
||||
elif [[ $# -ne 1 || "$1" == "-h" || "$1" == "--help" ]]; then
|
||||
print_help
|
||||
exit 1
|
||||
fi
|
||||
|
||||
package_path="$1"
|
||||
if [[ ! -f "$package_path" ]]; then
|
||||
echo "File '$package_path' does not exist!"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# Copy the .deb to working directory.
|
||||
cp "$package_path" "${working_dir}/"
|
||||
cd ${working_dir}
|
||||
|
||||
extension="${package_path##*.}"
|
||||
|
||||
if [[ "$extension" == "deb" ]]; then
|
||||
# Extract version and offering from deb name.
|
||||
package_name=`echo $(basename "$package_path") | sed 's/.deb$//'`
|
||||
version=`echo ${package_name} | cut -d '_' -f 2 | rev | cut -d '-' -f 2- | rev | tr '+~' '__'`
|
||||
dockerfile_path="${working_dir}/memgraph_deb.dockerfile"
|
||||
elif [[ "$extension" == "rpm" ]]; then
|
||||
# Extract version and offering from deb name.
|
||||
package_name=`echo $(basename "$package_path") | sed 's/.rpm$//'`
|
||||
version=`echo ${package_name} | cut -d '-' -f 2 | rev | cut -d '-' -f 2- | rev`
|
||||
version=${version%_1}
|
||||
dockerfile_path="${working_dir}/memgraph_rpm.dockerfile"
|
||||
else
|
||||
echo "Invalid file sent as the package"
|
||||
print_help
|
||||
exit 1
|
||||
fi
|
||||
|
||||
image_name="memgraph:${version}"
|
||||
image_package_name="memgraph-${version}-docker.tar.gz"
|
||||
|
||||
# Build docker image.
|
||||
docker build -t ${image_name} ${tag_latest} -f ${dockerfile_path} \
|
||||
--build-arg BINARY_NAME=${package_name} \
|
||||
--build-arg EXTENSION=${extension} \
|
||||
--build-arg TARGETARCH="" .
|
||||
docker save ${image_name} ${latest_image} | gzip > ${image_package_name}
|
||||
rm "${package_name}.${extension}"
|
||||
echo "Built Docker image at '${working_dir}/${image_package_name}'"
|
||||
@@ -104,7 +104,9 @@ def retry(retry_limit, timeout=100):
|
||||
except Exception:
|
||||
time.sleep(timeout)
|
||||
return func(*args, **kwargs)
|
||||
|
||||
return wrapper
|
||||
|
||||
return inner_func
|
||||
|
||||
|
||||
@@ -163,8 +165,15 @@ def format_version(variant, version, offering, distance=None, shorthash=None, su
|
||||
|
||||
# Parse arguments.
|
||||
parser = argparse.ArgumentParser(description="Get the current version of Memgraph.")
|
||||
parser.add_argument("--open-source", action="store_true", help="set the current offering to 'open-source'")
|
||||
parser.add_argument("version", help="manual version override, if supplied the version isn't " "determined using git")
|
||||
parser.add_argument(
|
||||
"--open-source",
|
||||
action="store_true",
|
||||
help="set the current offering to 'open-source'",
|
||||
)
|
||||
parser.add_argument(
|
||||
"version",
|
||||
help="manual version override, if supplied the version isn't " "determined using git",
|
||||
)
|
||||
parser.add_argument("suffix", help="custom suffix for the current version being built")
|
||||
parser.add_argument(
|
||||
"--variant",
|
||||
@@ -173,7 +182,9 @@ parser.add_argument(
|
||||
help="which variant of the version string should be generated",
|
||||
)
|
||||
parser.add_argument(
|
||||
"--memgraph-root-dir", help="The root directory of the checked out " "Memgraph repository.", default="."
|
||||
"--memgraph-root-dir",
|
||||
help="The root directory of the checked out " "Memgraph repository.",
|
||||
default=".",
|
||||
)
|
||||
args = parser.parse_args()
|
||||
|
||||
@@ -256,14 +267,27 @@ for version in versions:
|
||||
if current_version is None:
|
||||
raise Exception("You are attempting to determine the version for a very " "old version of Memgraph!")
|
||||
version, branch, master_branch_merge = current_version
|
||||
distance = int(get_output("git", "rev-list", "--count", "--first-parent", master_branch_merge + ".." + current_hash))
|
||||
distance = int(
|
||||
get_output(
|
||||
"git",
|
||||
"rev-list",
|
||||
"--count",
|
||||
"--first-parent",
|
||||
master_branch_merge + ".." + current_hash,
|
||||
)
|
||||
)
|
||||
version_str = ".".join(map(str, version)) + ".0"
|
||||
if distance == 0:
|
||||
print(format_version(args.variant, version_str, offering, suffix=args.suffix), end="")
|
||||
else:
|
||||
print(
|
||||
format_version(
|
||||
args.variant, version_str, offering, distance=distance, shorthash=current_hash_short, suffix=args.suffix
|
||||
args.variant,
|
||||
version_str,
|
||||
offering,
|
||||
distance=distance,
|
||||
shorthash=current_hash_short,
|
||||
suffix=args.suffix,
|
||||
),
|
||||
end="",
|
||||
)
|
||||
|
||||
@@ -7,8 +7,8 @@ RUN yum -y update \
|
||||
# Do NOT be smart here and clean the cache because the container is used in the
|
||||
# stateful context.
|
||||
|
||||
RUN wget -q https://s3-eu-west-1.amazonaws.com/deps.memgraph.io/${TOOLCHAIN_VERSION}/${TOOLCHAIN_VERSION}-binaries-centos-7.tar.gz \
|
||||
-O ${TOOLCHAIN_VERSION}-binaries-centos-7.tar.gz \
|
||||
&& tar xzvf ${TOOLCHAIN_VERSION}-binaries-centos-7.tar.gz -C /opt
|
||||
RUN wget -q https://s3-eu-west-1.amazonaws.com/deps.memgraph.io/${TOOLCHAIN_VERSION}/${TOOLCHAIN_VERSION}-binaries-centos-7-x86_64.tar.gz \
|
||||
-O ${TOOLCHAIN_VERSION}-binaries-centos-7-x86_64.tar.gz \
|
||||
&& tar xzvf ${TOOLCHAIN_VERSION}-binaries-centos-7-x86_64.tar.gz -C /opt
|
||||
|
||||
ENTRYPOINT ["sleep", "infinity"]
|
||||
|
||||
@@ -1,14 +0,0 @@
|
||||
FROM centos:8
|
||||
|
||||
ARG TOOLCHAIN_VERSION
|
||||
|
||||
RUN dnf -y update \
|
||||
&& dnf install -y wget git
|
||||
# Do NOT be smart here and clean the cache because the container is used in the
|
||||
# stateful context.
|
||||
|
||||
RUN wget -q https://s3-eu-west-1.amazonaws.com/deps.memgraph.io/${TOOLCHAIN_VERSION}/${TOOLCHAIN_VERSION}-binaries-centos-8.tar.gz \
|
||||
-O ${TOOLCHAIN_VERSION}-binaries-centos-8.tar.gz \
|
||||
&& tar xzvf ${TOOLCHAIN_VERSION}-binaries-centos-8.tar.gz -C /opt
|
||||
|
||||
ENTRYPOINT ["sleep", "infinity"]
|
||||
14
release/package/centos-9/Dockerfile
Normal file
14
release/package/centos-9/Dockerfile
Normal file
@@ -0,0 +1,14 @@
|
||||
FROM quay.io/centos/centos:stream9
|
||||
|
||||
ARG TOOLCHAIN_VERSION
|
||||
|
||||
RUN yum -y update \
|
||||
&& yum install -y wget git
|
||||
# Do NOT be smart here and clean the cache because the container is used in the
|
||||
# stateful context.
|
||||
|
||||
RUN wget -q https://s3-eu-west-1.amazonaws.com/deps.memgraph.io/${TOOLCHAIN_VERSION}/${TOOLCHAIN_VERSION}-binaries-centos-9-x86_64.tar.gz \
|
||||
-O ${TOOLCHAIN_VERSION}-binaries-centos-9-x86_64.tar.gz \
|
||||
&& tar xzvf ${TOOLCHAIN_VERSION}-binaries-centos-9-x86_64.tar.gz -C /opt
|
||||
|
||||
ENTRYPOINT ["sleep", "infinity"]
|
||||
@@ -10,8 +10,8 @@ RUN apt update && apt install -y \
|
||||
# Do NOT be smart here and clean the cache because the container is used in the
|
||||
# stateful context.
|
||||
|
||||
RUN wget -q https://s3-eu-west-1.amazonaws.com/deps.memgraph.io/${TOOLCHAIN_VERSION}/${TOOLCHAIN_VERSION}-binaries-debian-10.tar.gz \
|
||||
-O ${TOOLCHAIN_VERSION}-binaries-debian-10.tar.gz \
|
||||
&& tar xzvf ${TOOLCHAIN_VERSION}-binaries-debian-10.tar.gz -C /opt
|
||||
RUN wget -q https://s3-eu-west-1.amazonaws.com/deps.memgraph.io/${TOOLCHAIN_VERSION}/${TOOLCHAIN_VERSION}-binaries-debian-10-amd64.tar.gz \
|
||||
-O ${TOOLCHAIN_VERSION}-binaries-debian-10-amd64.tar.gz \
|
||||
&& tar xzvf ${TOOLCHAIN_VERSION}-binaries-debian-10-amd64.tar.gz -C /opt
|
||||
|
||||
ENTRYPOINT ["sleep", "infinity"]
|
||||
|
||||
17
release/package/debian-11-arm/Dockerfile
Normal file
17
release/package/debian-11-arm/Dockerfile
Normal file
@@ -0,0 +1,17 @@
|
||||
FROM debian:11
|
||||
|
||||
ARG TOOLCHAIN_VERSION
|
||||
|
||||
# Stops tzdata interactive configuration.
|
||||
ENV DEBIAN_FRONTEND=noninteractive
|
||||
|
||||
RUN apt update && apt install -y \
|
||||
ca-certificates wget git
|
||||
# Do NOT be smart here and clean the cache because the container is used in the
|
||||
# stateful context.
|
||||
|
||||
RUN wget -q https://s3-eu-west-1.amazonaws.com/deps.memgraph.io/${TOOLCHAIN_VERSION}/${TOOLCHAIN_VERSION}-binaries-debian-11-arm64.tar.gz \
|
||||
-O ${TOOLCHAIN_VERSION}-binaries-debian-11-arm64.tar.gz \
|
||||
&& tar xzvf ${TOOLCHAIN_VERSION}-binaries-debian-11-arm64.tar.gz -C /opt
|
||||
|
||||
ENTRYPOINT ["sleep", "infinity"]
|
||||
@@ -10,8 +10,8 @@ RUN apt update && apt install -y \
|
||||
# Do NOT be smart here and clean the cache because the container is used in the
|
||||
# stateful context.
|
||||
|
||||
RUN wget -q https://s3-eu-west-1.amazonaws.com/deps.memgraph.io/${TOOLCHAIN_VERSION}/${TOOLCHAIN_VERSION}-binaries-debian-11.tar.gz \
|
||||
-O ${TOOLCHAIN_VERSION}-binaries-debian-11.tar.gz \
|
||||
&& tar xzvf ${TOOLCHAIN_VERSION}-binaries-debian-11.tar.gz -C /opt
|
||||
RUN wget -q https://s3-eu-west-1.amazonaws.com/deps.memgraph.io/${TOOLCHAIN_VERSION}/${TOOLCHAIN_VERSION}-binaries-debian-11-amd64.tar.gz \
|
||||
-O ${TOOLCHAIN_VERSION}-binaries-debian-11-amd64.tar.gz \
|
||||
&& tar xzvf ${TOOLCHAIN_VERSION}-binaries-debian-11-amd64.tar.gz -C /opt
|
||||
|
||||
ENTRYPOINT ["sleep", "infinity"]
|
||||
|
||||
@@ -4,10 +4,10 @@ services:
|
||||
build:
|
||||
context: centos-7
|
||||
container_name: "mgbuild_centos-7"
|
||||
mgbuild_centos-8:
|
||||
mgbuild_centos-9:
|
||||
build:
|
||||
context: centos-8
|
||||
container_name: "mgbuild_centos-8"
|
||||
context: centos-9
|
||||
container_name: "mgbuild_centos-9"
|
||||
mgbuild_debian-10:
|
||||
build:
|
||||
context: debian-10
|
||||
@@ -24,3 +24,7 @@ services:
|
||||
build:
|
||||
context: ubuntu-20.04
|
||||
container_name: "mgbuild_ubuntu-20.04"
|
||||
mgbuild_ubuntu-22.04:
|
||||
build:
|
||||
context: ubuntu-22.04
|
||||
container_name: "mgbuild_ubuntu-22.04"
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
set -Eeuo pipefail
|
||||
|
||||
SCRIPT_DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )"
|
||||
SUPPORTED_OS=(centos-7 centos-8 debian-10 debian-11 ubuntu-18.04 ubuntu-20.04)
|
||||
SUPPORTED_OS=(centos-7 centos-9 debian-10 debian-11 ubuntu-18.04 ubuntu-20.04 ubuntu-22.04 debian-11-arm)
|
||||
PROJECT_ROOT="$SCRIPT_DIR/../.."
|
||||
TOOLCHAIN_VERSION="toolchain-v4"
|
||||
ACTIVATE_TOOLCHAIN="source /opt/${TOOLCHAIN_VERSION}/activate"
|
||||
@@ -67,14 +67,18 @@ make_package () {
|
||||
# environment/os/{os}.sh does not come within the toolchain package. When
|
||||
# migrating to the next version of toolchain do that, and remove the
|
||||
# TOOLCHAIN_RUN_DEPS installation from here.
|
||||
echo "Installing dependencies..."
|
||||
echo "Installing dependencies using '/memgraph/environment/os/$os.sh' script..."
|
||||
docker exec "$build_container" bash -c "/memgraph/environment/os/$os.sh install TOOLCHAIN_RUN_DEPS"
|
||||
docker exec "$build_container" bash -c "/memgraph/environment/os/$os.sh install MEMGRAPH_BUILD_DEPS"
|
||||
|
||||
echo "Building targeted package..."
|
||||
docker exec "$build_container" bash -c "cd /memgraph && $ACTIVATE_TOOLCHAIN && ./init"
|
||||
docker exec "$build_container" bash -c "cd $container_build_dir && rm -rf ./*"
|
||||
docker exec "$build_container" bash -c "cd $container_build_dir && $ACTIVATE_TOOLCHAIN && cmake -DCMAKE_BUILD_TYPE=release $telemetry_id_override_flag .."
|
||||
if [[ "$os" == "debian-11-arm" ]]; then
|
||||
docker exec "$build_container" bash -c "cd $container_build_dir && $ACTIVATE_TOOLCHAIN && cmake -DCMAKE_BUILD_TYPE=release -DMG_ARCH="ARM64" $telemetry_id_override_flag .."
|
||||
else
|
||||
docker exec "$build_container" bash -c "cd $container_build_dir && $ACTIVATE_TOOLCHAIN && cmake -DCMAKE_BUILD_TYPE=release $telemetry_id_override_flag .."
|
||||
fi
|
||||
# ' is used instead of " because we need to run make within the allowed
|
||||
# container resources.
|
||||
# shellcheck disable=SC2016
|
||||
@@ -106,7 +110,7 @@ case "$1" in
|
||||
last_package_name=$(cd "$HOST_OUTPUT_DIR/$based_on_os" && ls -t memgraph* | head -1)
|
||||
docker_build_folder="$PROJECT_ROOT/release/docker"
|
||||
cd "$docker_build_folder"
|
||||
./package_deb_docker --latest "$HOST_OUTPUT_DIR/$based_on_os/$last_package_name"
|
||||
./package_docker --latest "$HOST_OUTPUT_DIR/$based_on_os/$last_package_name"
|
||||
# shellcheck disable=SC2012
|
||||
docker_image_name=$(cd "$docker_build_folder" && ls -t memgraph* | head -1)
|
||||
docker_host_folder="$HOST_OUTPUT_DIR/docker"
|
||||
|
||||
@@ -10,8 +10,8 @@ RUN apt update && apt install -y \
|
||||
# Do NOT be smart here and clean the cache because the container is used in the
|
||||
# stateful context.
|
||||
|
||||
RUN wget -q https://s3-eu-west-1.amazonaws.com/deps.memgraph.io/${TOOLCHAIN_VERSION}/${TOOLCHAIN_VERSION}-binaries-ubuntu-18.04.tar.gz \
|
||||
-O ${TOOLCHAIN_VERSION}-binaries-ubuntu-18.04.tar.gz \
|
||||
&& tar xzvf ${TOOLCHAIN_VERSION}-binaries-ubuntu-18.04.tar.gz -C /opt
|
||||
RUN wget -q https://s3-eu-west-1.amazonaws.com/deps.memgraph.io/${TOOLCHAIN_VERSION}/${TOOLCHAIN_VERSION}-binaries-ubuntu-18.04-amd64.tar.gz \
|
||||
-O ${TOOLCHAIN_VERSION}-binaries-ubuntu-18.04-amd64.tar.gz \
|
||||
&& tar xzvf ${TOOLCHAIN_VERSION}-binaries-ubuntu-18.04-amd64.tar.gz -C /opt
|
||||
|
||||
ENTRYPOINT ["sleep", "infinity"]
|
||||
|
||||
@@ -10,8 +10,8 @@ RUN apt update && apt install -y \
|
||||
# Do NOT be smart here and clean the cache because the container is used in the
|
||||
# stateful context.
|
||||
|
||||
RUN wget -q https://s3-eu-west-1.amazonaws.com/deps.memgraph.io/${TOOLCHAIN_VERSION}/${TOOLCHAIN_VERSION}-binaries-ubuntu-20.04.tar.gz \
|
||||
-O ${TOOLCHAIN_VERSION}-binaries-ubuntu-20.04.tar.gz \
|
||||
&& tar xzvf ${TOOLCHAIN_VERSION}-binaries-ubuntu-20.04.tar.gz -C /opt
|
||||
RUN wget -q https://s3-eu-west-1.amazonaws.com/deps.memgraph.io/${TOOLCHAIN_VERSION}/${TOOLCHAIN_VERSION}-binaries-ubuntu-20.04-amd64.tar.gz \
|
||||
-O ${TOOLCHAIN_VERSION}-binaries-ubuntu-20.04-amd64.tar.gz \
|
||||
&& tar xzvf ${TOOLCHAIN_VERSION}-binaries-ubuntu-20.04-amd64.tar.gz -C /opt
|
||||
|
||||
ENTRYPOINT ["sleep", "infinity"]
|
||||
|
||||
17
release/package/ubuntu-22.04/Dockerfile
Normal file
17
release/package/ubuntu-22.04/Dockerfile
Normal file
@@ -0,0 +1,17 @@
|
||||
FROM ubuntu:22.04
|
||||
|
||||
ARG TOOLCHAIN_VERSION
|
||||
|
||||
# Stops tzdata interactive configuration.
|
||||
ENV DEBIAN_FRONTEND=noninteractive
|
||||
|
||||
RUN apt update && apt install -y \
|
||||
ca-certificates wget git
|
||||
# Do NOT be smart here and clean the cache because the container is used in the
|
||||
# stateful context.
|
||||
|
||||
RUN wget -q https://s3-eu-west-1.amazonaws.com/deps.memgraph.io/${TOOLCHAIN_VERSION}/${TOOLCHAIN_VERSION}-binaries-ubuntu-22.04-amd64.tar.gz \
|
||||
-O ${TOOLCHAIN_VERSION}-binaries-ubuntu-22.04-amd64.tar.gz \
|
||||
&& tar xzvf ${TOOLCHAIN_VERSION}-binaries-ubuntu-22.04-amd64.tar.gz -C /opt
|
||||
|
||||
ENTRYPOINT ["sleep", "infinity"]
|
||||
@@ -1,4 +1,4 @@
|
||||
// Copyright 2021 Memgraph Ltd.
|
||||
// Copyright 2022 Memgraph Ltd.
|
||||
//
|
||||
// Licensed as a Memgraph Enterprise file under the Memgraph Enterprise
|
||||
// License (the "License"); by using this file, you agree to be bound by the terms of the License, and you may not use
|
||||
@@ -18,7 +18,7 @@
|
||||
#include "utils/logging.hpp"
|
||||
#include "utils/string.hpp"
|
||||
|
||||
namespace audit {
|
||||
namespace memgraph::audit {
|
||||
|
||||
// Helper function that converts a `storage::PropertyValue` to `nlohmann::json`.
|
||||
inline nlohmann::json PropertyValueToJson(const storage::PropertyValue &pv) {
|
||||
@@ -143,4 +143,4 @@ void Log::Flush() {
|
||||
log_.Sync();
|
||||
}
|
||||
|
||||
} // namespace audit
|
||||
} // namespace memgraph::audit
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
// Copyright 2021 Memgraph Ltd.
|
||||
// Copyright 2022 Memgraph Ltd.
|
||||
//
|
||||
// Licensed as a Memgraph Enterprise file under the Memgraph Enterprise
|
||||
// License (the "License"); by using this file, you agree to be bound by the terms of the License, and you may not use
|
||||
@@ -17,7 +17,7 @@
|
||||
#include "utils/file.hpp"
|
||||
#include "utils/scheduler.hpp"
|
||||
|
||||
namespace audit {
|
||||
namespace memgraph::audit {
|
||||
|
||||
const uint64_t kBufferSizeDefault = 100000;
|
||||
const uint64_t kBufferFlushIntervalMillisDefault = 200;
|
||||
@@ -71,4 +71,4 @@ class Log {
|
||||
std::mutex lock_;
|
||||
};
|
||||
|
||||
} // namespace audit
|
||||
} // namespace memgraph::audit
|
||||
|
||||
@@ -11,7 +11,7 @@ find_package(gflags REQUIRED)
|
||||
|
||||
add_library(mg-auth STATIC ${auth_src_files})
|
||||
target_link_libraries(mg-auth json libbcrypt gflags fmt::fmt)
|
||||
target_link_libraries(mg-auth mg-utils mg-kvstore)
|
||||
target_link_libraries(mg-auth mg-utils mg-kvstore mg-license )
|
||||
|
||||
target_link_libraries(mg-auth ${Seccomp_LIBRARIES})
|
||||
target_include_directories(mg-auth SYSTEM PRIVATE ${Seccomp_INCLUDE_DIRS})
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
// Copyright 2021 Memgraph Ltd.
|
||||
// Copyright 2022 Memgraph Ltd.
|
||||
//
|
||||
// Licensed as a Memgraph Enterprise file under the Memgraph Enterprise
|
||||
// License (the "License"); by using this file, you agree to be bound by the terms of the License, and you may not use
|
||||
@@ -42,8 +42,7 @@ DEFINE_VALIDATED_int32(auth_module_timeout_ms, 10000,
|
||||
"response from the auth module.",
|
||||
FLAG_IN_RANGE(100, 1800000));
|
||||
|
||||
namespace auth {
|
||||
|
||||
namespace memgraph::auth {
|
||||
const std::string kUserPrefix = "user:";
|
||||
const std::string kRolePrefix = "role:";
|
||||
const std::string kLinkPrefix = "link:";
|
||||
@@ -316,4 +315,4 @@ std::vector<auth::User> Auth::AllUsersForRole(const std::string &rolename_orig)
|
||||
return ret;
|
||||
}
|
||||
|
||||
} // namespace auth
|
||||
} // namespace memgraph::auth
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
// Copyright 2021 Memgraph Ltd.
|
||||
// Copyright 2022 Memgraph Ltd.
|
||||
//
|
||||
// Licensed as a Memgraph Enterprise file under the Memgraph Enterprise
|
||||
// License (the "License"); by using this file, you agree to be bound by the terms of the License, and you may not use
|
||||
@@ -18,8 +18,7 @@
|
||||
#include "kvstore/kvstore.hpp"
|
||||
#include "utils/settings.hpp"
|
||||
|
||||
namespace auth {
|
||||
|
||||
namespace memgraph::auth {
|
||||
/**
|
||||
* This class serves as the main Authentication/Authorization storage.
|
||||
* It provides functions for managing Users, Roles and Permissions.
|
||||
@@ -163,4 +162,4 @@ class Auth final {
|
||||
kvstore::KVStore storage_;
|
||||
auth::Module module_;
|
||||
};
|
||||
} // namespace auth
|
||||
} // namespace memgraph::auth
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
// Copyright 2021 Memgraph Ltd.
|
||||
// Copyright 2022 Memgraph Ltd.
|
||||
//
|
||||
// Licensed as a Memgraph Enterprise file under the Memgraph Enterprise
|
||||
// License (the "License"); by using this file, you agree to be bound by the terms of the License, and you may not use
|
||||
@@ -12,8 +12,7 @@
|
||||
|
||||
#include "auth/exceptions.hpp"
|
||||
|
||||
namespace auth {
|
||||
|
||||
namespace memgraph::auth {
|
||||
const std::string EncryptPassword(const std::string &password) {
|
||||
char salt[BCRYPT_HASHSIZE];
|
||||
char hash[BCRYPT_HASHSIZE];
|
||||
@@ -40,4 +39,4 @@ bool VerifyPassword(const std::string &password, const std::string &hash) {
|
||||
return ret == 0;
|
||||
}
|
||||
|
||||
} // namespace auth
|
||||
} // namespace memgraph::auth
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
// Copyright 2021 Memgraph Ltd.
|
||||
// Copyright 2022 Memgraph Ltd.
|
||||
//
|
||||
// Licensed as a Memgraph Enterprise file under the Memgraph Enterprise
|
||||
// License (the "License"); by using this file, you agree to be bound by the terms of the License, and you may not use
|
||||
@@ -10,12 +10,11 @@
|
||||
|
||||
#include <string>
|
||||
|
||||
namespace auth {
|
||||
|
||||
namespace memgraph::auth {
|
||||
/// @throw AuthException if unable to encrypt the password.
|
||||
const std::string EncryptPassword(const std::string &password);
|
||||
|
||||
/// @throw AuthException if unable to verify the password.
|
||||
bool VerifyPassword(const std::string &password, const std::string &hash);
|
||||
|
||||
} // namespace auth
|
||||
} // namespace memgraph::auth
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
// Copyright 2021 Memgraph Ltd.
|
||||
// Copyright 2022 Memgraph Ltd.
|
||||
//
|
||||
// Use of this software is governed by the Business Source License
|
||||
// included in the file licenses/BSL.txt; by using this file, you agree to be bound by the terms of the Business Source
|
||||
@@ -13,8 +13,7 @@
|
||||
|
||||
#include "utils/exceptions.hpp"
|
||||
|
||||
namespace auth {
|
||||
|
||||
namespace memgraph::auth {
|
||||
/**
|
||||
* This exception class is thrown for all exceptions that can occur when dealing
|
||||
* with the Auth library.
|
||||
@@ -23,4 +22,4 @@ class AuthException : public utils::BasicException {
|
||||
public:
|
||||
using utils::BasicException::BasicException;
|
||||
};
|
||||
} // namespace auth
|
||||
} // namespace memgraph::auth
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
// Copyright 2021 Memgraph Ltd.
|
||||
// Copyright 2022 Memgraph Ltd.
|
||||
//
|
||||
// Licensed as a Memgraph Enterprise file under the Memgraph Enterprise
|
||||
// License (the "License"); by using this file, you agree to be bound by the terms of the License, and you may not use
|
||||
@@ -22,13 +22,23 @@
|
||||
// NOLINTNEXTLINE(cppcoreguidelines-avoid-non-const-global-variables)
|
||||
DEFINE_bool(auth_password_permit_null, true, "Set to false to disable null passwords.");
|
||||
|
||||
constexpr std::string_view default_password_regex = ".+";
|
||||
inline constexpr std::string_view default_password_regex = ".+";
|
||||
// NOLINTNEXTLINE(cppcoreguidelines-avoid-non-const-global-variables)
|
||||
DEFINE_string(auth_password_strength_regex, default_password_regex.data(),
|
||||
"The regular expression that should be used to match the entire "
|
||||
"entered password to ensure its strength.");
|
||||
|
||||
namespace auth {
|
||||
namespace memgraph::auth {
|
||||
namespace {
|
||||
// Constant list of all available permissions.
|
||||
const std::vector<Permission> kPermissionsAll = {
|
||||
Permission::MATCH, Permission::CREATE, Permission::MERGE, Permission::DELETE,
|
||||
Permission::SET, Permission::REMOVE, Permission::INDEX, Permission::STATS,
|
||||
Permission::CONSTRAINT, Permission::DUMP, Permission::AUTH, Permission::REPLICATION,
|
||||
Permission::DURABILITY, Permission::READ_FILE, Permission::FREE_MEMORY, Permission::TRIGGER,
|
||||
Permission::CONFIG, Permission::STREAM, Permission::MODULE_READ, Permission::MODULE_WRITE,
|
||||
Permission::WEBSOCKET};
|
||||
} // namespace
|
||||
|
||||
std::string PermissionToString(Permission permission) {
|
||||
switch (permission) {
|
||||
@@ -68,6 +78,14 @@ std::string PermissionToString(Permission permission) {
|
||||
return "AUTH";
|
||||
case Permission::STREAM:
|
||||
return "STREAM";
|
||||
case Permission::MODULE_READ:
|
||||
return "MODULE_READ";
|
||||
case Permission::MODULE_WRITE:
|
||||
return "MODULE_WRITE";
|
||||
case Permission::WEBSOCKET:
|
||||
return "WEBSOCKET";
|
||||
case Permission::LABELS:
|
||||
return "LABELS";
|
||||
}
|
||||
}
|
||||
|
||||
@@ -167,19 +185,107 @@ bool operator==(const Permissions &first, const Permissions &second) {
|
||||
|
||||
bool operator!=(const Permissions &first, const Permissions &second) { return !(first == second); }
|
||||
|
||||
LabelPermissions::LabelPermissions(const std::unordered_set<std::string> &grants,
|
||||
const std::unordered_set<std::string> &denies)
|
||||
: grants_(grants), denies_(denies) {}
|
||||
|
||||
PermissionLevel LabelPermissions::Has(const std::string &permission) const {
|
||||
if (denies_.find(permission) != denies_.end()) {
|
||||
return PermissionLevel::DENY;
|
||||
}
|
||||
|
||||
if (grants_.find(permission) != denies_.end()) {
|
||||
return PermissionLevel::GRANT;
|
||||
}
|
||||
|
||||
return PermissionLevel::NEUTRAL;
|
||||
}
|
||||
|
||||
void LabelPermissions::Grant(const std::string &permission) {
|
||||
auto deniedPermissionIter = denies_.find(permission);
|
||||
|
||||
if (deniedPermissionIter != denies_.end()) {
|
||||
denies_.erase(deniedPermissionIter);
|
||||
}
|
||||
|
||||
if (grants_.find(permission) == grants_.end()) {
|
||||
grants_.insert(permission);
|
||||
}
|
||||
}
|
||||
|
||||
void LabelPermissions::Revoke(const std::string &permission) {
|
||||
auto deniedPermissionIter = denies_.find(permission);
|
||||
auto grantedPermissionIter = grants_.find(permission);
|
||||
|
||||
if (deniedPermissionIter != denies_.end()) {
|
||||
denies_.erase(deniedPermissionIter);
|
||||
}
|
||||
|
||||
if (grantedPermissionIter != grants_.end()) {
|
||||
grants_.erase(grantedPermissionIter);
|
||||
}
|
||||
}
|
||||
|
||||
void LabelPermissions::Deny(const std::string &permission) {
|
||||
auto grantedPermissionIter = grants_.find(permission);
|
||||
|
||||
if (grantedPermissionIter != grants_.end()) {
|
||||
grants_.erase(grantedPermissionIter);
|
||||
}
|
||||
|
||||
if (denies_.find(permission) == denies_.end()) {
|
||||
denies_.insert(permission);
|
||||
}
|
||||
}
|
||||
|
||||
std::unordered_set<std::string> LabelPermissions::GetGrants() const { return grants_; }
|
||||
|
||||
std::unordered_set<std::string> LabelPermissions::GetDenies() const { return denies_; }
|
||||
|
||||
nlohmann::json LabelPermissions::Serialize() const {
|
||||
nlohmann::json data = nlohmann::json::object();
|
||||
data["grants"] = grants_;
|
||||
data["denies"] = denies_;
|
||||
return data;
|
||||
}
|
||||
|
||||
LabelPermissions LabelPermissions::Deserialize(const nlohmann::json &data) {
|
||||
if (!data.is_object()) {
|
||||
throw AuthException("Couldn't load permissions data!");
|
||||
}
|
||||
|
||||
return {LabelPermissions(data["grants"], data["denies"])};
|
||||
}
|
||||
|
||||
std::unordered_set<std::string> LabelPermissions::grants() const { return grants_; }
|
||||
std::unordered_set<std::string> LabelPermissions::denies() const { return denies_; }
|
||||
|
||||
bool operator==(const LabelPermissions &first, const LabelPermissions &second) {
|
||||
return first.grants() == second.grants() && first.denies() == second.denies();
|
||||
}
|
||||
|
||||
bool operator!=(const LabelPermissions &first, const LabelPermissions &second) { return !(first == second); }
|
||||
|
||||
Role::Role(const std::string &rolename) : rolename_(utils::ToLowerCase(rolename)) {}
|
||||
|
||||
Role::Role(const std::string &rolename, const Permissions &permissions)
|
||||
: rolename_(utils::ToLowerCase(rolename)), permissions_(permissions) {}
|
||||
|
||||
Role::Role(const std::string &rolename, const Permissions &permissions, const LabelPermissions &labelPermissions)
|
||||
: rolename_(utils::ToLowerCase(rolename)), permissions_(permissions), labelPermissions_(labelPermissions) {}
|
||||
|
||||
const std::string &Role::rolename() const { return rolename_; }
|
||||
const Permissions &Role::permissions() const { return permissions_; }
|
||||
Permissions &Role::permissions() { return permissions_; }
|
||||
|
||||
LabelPermissions &Role::labelPermissions() { return labelPermissions_; }
|
||||
|
||||
nlohmann::json Role::Serialize() const {
|
||||
nlohmann::json data = nlohmann::json::object();
|
||||
data["rolename"] = rolename_;
|
||||
data["permissions"] = permissions_.Serialize();
|
||||
data["labelPermissions"] = labelPermissions_.Serialize();
|
||||
|
||||
return data;
|
||||
}
|
||||
|
||||
@@ -191,7 +297,9 @@ Role Role::Deserialize(const nlohmann::json &data) {
|
||||
throw AuthException("Couldn't load role data!");
|
||||
}
|
||||
auto permissions = Permissions::Deserialize(data["permissions"]);
|
||||
return {data["rolename"], permissions};
|
||||
auto labelPermissions = LabelPermissions::Deserialize(data["labelPermissions"]);
|
||||
|
||||
return {data["rolename"], permissions, labelPermissions};
|
||||
}
|
||||
|
||||
bool operator==(const Role &first, const Role &second) {
|
||||
@@ -203,6 +311,13 @@ User::User(const std::string &username) : username_(utils::ToLowerCase(username)
|
||||
User::User(const std::string &username, const std::string &password_hash, const Permissions &permissions)
|
||||
: username_(utils::ToLowerCase(username)), password_hash_(password_hash), permissions_(permissions) {}
|
||||
|
||||
User::User(const std::string &username, const std::string &password_hash, const Permissions &permissions,
|
||||
const LabelPermissions &labelPermissions)
|
||||
: username_(utils::ToLowerCase(username)),
|
||||
password_hash_(password_hash),
|
||||
permissions_(permissions),
|
||||
labelPermissions_(labelPermissions) {}
|
||||
|
||||
bool User::CheckPassword(const std::string &password) {
|
||||
if (password_hash_.empty()) return true;
|
||||
return VerifyPassword(password, password_hash_);
|
||||
@@ -255,6 +370,8 @@ const std::string &User::username() const { return username_; }
|
||||
const Permissions &User::permissions() const { return permissions_; }
|
||||
Permissions &User::permissions() { return permissions_; }
|
||||
|
||||
LabelPermissions &User::labelPermissions() { return labelPermissions_; }
|
||||
|
||||
const Role *User::role() const {
|
||||
if (role_.has_value()) {
|
||||
return &role_.value();
|
||||
@@ -267,6 +384,7 @@ nlohmann::json User::Serialize() const {
|
||||
data["username"] = username_;
|
||||
data["password_hash"] = password_hash_;
|
||||
data["permissions"] = permissions_.Serialize();
|
||||
data["labelPermissions"] = labelPermissions_.Serialize();
|
||||
// The role shouldn't be serialized here, it is stored as a foreign key.
|
||||
return data;
|
||||
}
|
||||
@@ -279,11 +397,14 @@ User User::Deserialize(const nlohmann::json &data) {
|
||||
throw AuthException("Couldn't load user data!");
|
||||
}
|
||||
auto permissions = Permissions::Deserialize(data["permissions"]);
|
||||
return {data["username"], data["password_hash"], permissions};
|
||||
auto labelPermissions = LabelPermissions::Deserialize(data["labelPermissions"]);
|
||||
|
||||
return {data["username"], data["password_hash"], permissions, labelPermissions};
|
||||
}
|
||||
|
||||
bool operator==(const User &first, const User &second) {
|
||||
return first.username_ == second.username_ && first.password_hash_ == second.password_hash_ &&
|
||||
first.permissions_ == second.permissions_ && first.role_ == second.role_;
|
||||
}
|
||||
} // namespace auth
|
||||
|
||||
} // namespace memgraph::auth
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
// Copyright 2021 Memgraph Ltd.
|
||||
// Copyright 2022 Memgraph Ltd.
|
||||
//
|
||||
// Licensed as a Memgraph Enterprise file under the Memgraph Enterprise
|
||||
// License (the "License"); by using this file, you agree to be bound by the terms of the License, and you may not use
|
||||
@@ -12,42 +12,38 @@
|
||||
#include <string>
|
||||
|
||||
#include <json/json.hpp>
|
||||
#include <unordered_set>
|
||||
|
||||
namespace auth {
|
||||
|
||||
namespace memgraph::auth {
|
||||
// These permissions must have values that are applicable for usage in a
|
||||
// bitmask.
|
||||
// clang-format off
|
||||
enum class Permission : uint64_t {
|
||||
MATCH = 1,
|
||||
CREATE = 1U << 1U,
|
||||
MERGE = 1U << 2U,
|
||||
DELETE = 1U << 3U,
|
||||
SET = 1U << 4U,
|
||||
REMOVE = 1U << 5U,
|
||||
INDEX = 1U << 6U,
|
||||
STATS = 1U << 7U,
|
||||
CONSTRAINT = 1U << 8U,
|
||||
DUMP = 1U << 9U,
|
||||
REPLICATION = 1U << 10U,
|
||||
DURABILITY = 1U << 11U,
|
||||
READ_FILE = 1U << 12U,
|
||||
FREE_MEMORY = 1U << 13U,
|
||||
TRIGGER = 1U << 14U,
|
||||
CONFIG = 1U << 15U,
|
||||
AUTH = 1U << 16U,
|
||||
STREAM = 1U << 17U
|
||||
MATCH = 1,
|
||||
CREATE = 1U << 1U,
|
||||
MERGE = 1U << 2U,
|
||||
DELETE = 1U << 3U,
|
||||
SET = 1U << 4U,
|
||||
REMOVE = 1U << 5U,
|
||||
INDEX = 1U << 6U,
|
||||
STATS = 1U << 7U,
|
||||
CONSTRAINT = 1U << 8U,
|
||||
DUMP = 1U << 9U,
|
||||
REPLICATION = 1U << 10U,
|
||||
DURABILITY = 1U << 11U,
|
||||
READ_FILE = 1U << 12U,
|
||||
FREE_MEMORY = 1U << 13U,
|
||||
TRIGGER = 1U << 14U,
|
||||
CONFIG = 1U << 15U,
|
||||
AUTH = 1U << 16U,
|
||||
STREAM = 1U << 17U,
|
||||
MODULE_READ = 1U << 18U,
|
||||
MODULE_WRITE = 1U << 19U,
|
||||
WEBSOCKET = 1U << 20U,
|
||||
LABELS = 1U << 21U
|
||||
};
|
||||
// clang-format on
|
||||
|
||||
// Constant list of all available permissions.
|
||||
const std::vector<Permission> kPermissionsAll = {Permission::MATCH, Permission::CREATE, Permission::MERGE,
|
||||
Permission::DELETE, Permission::SET, Permission::REMOVE,
|
||||
Permission::INDEX, Permission::STATS, Permission::CONSTRAINT,
|
||||
Permission::DUMP, Permission::AUTH, Permission::REPLICATION,
|
||||
Permission::DURABILITY, Permission::READ_FILE, Permission::FREE_MEMORY,
|
||||
Permission::TRIGGER, Permission::CONFIG, Permission::STREAM};
|
||||
|
||||
// Function that converts a permission to its string representation.
|
||||
std::string PermissionToString(Permission permission);
|
||||
|
||||
@@ -94,16 +90,52 @@ bool operator==(const Permissions &first, const Permissions &second);
|
||||
|
||||
bool operator!=(const Permissions &first, const Permissions &second);
|
||||
|
||||
class LabelPermissions final {
|
||||
public:
|
||||
LabelPermissions(const std::unordered_set<std::string> &grants = {},
|
||||
const std::unordered_set<std::string> &denies = {});
|
||||
|
||||
PermissionLevel Has(const std::string &permission) const;
|
||||
|
||||
void Grant(const std::string &permission);
|
||||
|
||||
void Revoke(const std::string &permission);
|
||||
|
||||
void Deny(const std::string &permission);
|
||||
|
||||
std::unordered_set<std::string> GetGrants() const;
|
||||
std::unordered_set<std::string> GetDenies() const;
|
||||
|
||||
nlohmann::json Serialize() const;
|
||||
|
||||
/// @throw AuthException if unable to deserialize.
|
||||
static LabelPermissions Deserialize(const nlohmann::json &data);
|
||||
|
||||
std::unordered_set<std::string> grants() const;
|
||||
std::unordered_set<std::string> denies() const;
|
||||
|
||||
private:
|
||||
std::unordered_set<std::string> grants_{};
|
||||
std::unordered_set<std::string> denies_{};
|
||||
};
|
||||
|
||||
bool operator==(const LabelPermissions &first, const LabelPermissions &second);
|
||||
|
||||
bool operator!=(const LabelPermissions &first, const LabelPermissions &second);
|
||||
class Role final {
|
||||
public:
|
||||
Role(const std::string &rolename);
|
||||
|
||||
Role(const std::string &rolename, const Permissions &permissions);
|
||||
|
||||
Role(const std::string &rolename, const Permissions &permissions, const LabelPermissions &labelPermissions);
|
||||
|
||||
const std::string &rolename() const;
|
||||
const Permissions &permissions() const;
|
||||
Permissions &permissions();
|
||||
|
||||
LabelPermissions &labelPermissions();
|
||||
|
||||
nlohmann::json Serialize() const;
|
||||
|
||||
/// @throw AuthException if unable to deserialize.
|
||||
@@ -114,6 +146,7 @@ class Role final {
|
||||
private:
|
||||
std::string rolename_;
|
||||
Permissions permissions_;
|
||||
LabelPermissions labelPermissions_;
|
||||
};
|
||||
|
||||
bool operator==(const Role &first, const Role &second);
|
||||
@@ -125,6 +158,9 @@ class User final {
|
||||
|
||||
User(const std::string &username, const std::string &password_hash, const Permissions &permissions);
|
||||
|
||||
User(const std::string &username, const std::string &password_hash, const Permissions &permissions,
|
||||
const LabelPermissions &labelPermissions);
|
||||
|
||||
/// @throw AuthException if unable to verify the password.
|
||||
bool CheckPassword(const std::string &password);
|
||||
|
||||
@@ -144,6 +180,8 @@ class User final {
|
||||
|
||||
const Role *role() const;
|
||||
|
||||
LabelPermissions &labelPermissions();
|
||||
|
||||
nlohmann::json Serialize() const;
|
||||
|
||||
/// @throw AuthException if unable to deserialize.
|
||||
@@ -156,7 +194,9 @@ class User final {
|
||||
std::string password_hash_;
|
||||
Permissions permissions_;
|
||||
std::optional<Role> role_;
|
||||
LabelPermissions labelPermissions_;
|
||||
};
|
||||
|
||||
bool operator==(const User &first, const User &second);
|
||||
} // namespace auth
|
||||
|
||||
} // namespace memgraph::auth
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
// Copyright 2021 Memgraph Ltd.
|
||||
// Copyright 2022 Memgraph Ltd.
|
||||
//
|
||||
// Licensed as a Memgraph Enterprise file under the Memgraph Enterprise
|
||||
// License (the "License"); by using this file, you agree to be bound by the terms of the License, and you may not use
|
||||
@@ -153,7 +153,7 @@ int Target(void *arg) {
|
||||
// process and something really bad could happen.
|
||||
|
||||
// Get a pointer to the passed arguments.
|
||||
auto *ta = reinterpret_cast<auth::TargetArguments *>(arg);
|
||||
auto *ta = reinterpret_cast<memgraph::auth::TargetArguments *>(arg);
|
||||
|
||||
// Redirect `stdin` to `/dev/null`.
|
||||
int fd = open("/dev/null", O_RDONLY | O_CLOEXEC);
|
||||
@@ -312,8 +312,7 @@ nlohmann::json GetData(int fd, int timeout_millisec) {
|
||||
|
||||
} // namespace
|
||||
|
||||
namespace auth {
|
||||
|
||||
namespace memgraph::auth {
|
||||
Module::Module(const std::filesystem::path &module_executable_path) {
|
||||
if (!module_executable_path.empty()) {
|
||||
module_executable_path_ = std::filesystem::absolute(module_executable_path);
|
||||
@@ -447,4 +446,4 @@ void Module::Shutdown() {
|
||||
|
||||
Module::~Module() { Shutdown(); }
|
||||
|
||||
} // namespace auth
|
||||
} // namespace memgraph::auth
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
// Copyright 2021 Memgraph Ltd.
|
||||
// Copyright 2022 Memgraph Ltd.
|
||||
//
|
||||
// Licensed as a Memgraph Enterprise file under the Memgraph Enterprise
|
||||
// License (the "License"); by using this file, you agree to be bound by the terms of the License, and you may not use
|
||||
@@ -16,8 +16,7 @@
|
||||
|
||||
#include <json/json.hpp>
|
||||
|
||||
namespace auth {
|
||||
|
||||
namespace memgraph::auth {
|
||||
struct TargetArguments {
|
||||
std::filesystem::path module_executable_path;
|
||||
int pipe_to_module{-1};
|
||||
@@ -70,4 +69,4 @@ class Module final {
|
||||
int pipe_from_module_[2] = {-1, -1};
|
||||
};
|
||||
|
||||
} // namespace auth
|
||||
} // namespace memgraph::auth
|
||||
|
||||
@@ -18,19 +18,24 @@ roles_config = config["roles"]
|
||||
# Initialize LDAP server.
|
||||
tls = None
|
||||
if server_config["encryption"] != "disabled":
|
||||
cert_file = server_config["cert_file"] if server_config["cert_file"] \
|
||||
else None
|
||||
cert_file = server_config["cert_file"] if server_config["cert_file"] else None
|
||||
key_file = server_config["key_file"] if server_config["key_file"] else None
|
||||
ca_file = server_config["ca_file"] if server_config["ca_file"] else None
|
||||
validate = ssl.CERT_REQUIRED if server_config["validate_cert"] \
|
||||
else ssl.CERT_NONE
|
||||
tls = ldap3.Tls(local_private_key_file=key_file,
|
||||
local_certificate_file=cert_file,
|
||||
ca_certs_file=ca_file,
|
||||
validate=validate)
|
||||
validate = ssl.CERT_REQUIRED if server_config["validate_cert"] else ssl.CERT_NONE
|
||||
tls = ldap3.Tls(
|
||||
local_private_key_file=key_file,
|
||||
local_certificate_file=cert_file,
|
||||
ca_certs_file=ca_file,
|
||||
validate=validate,
|
||||
)
|
||||
use_ssl = server_config["encryption"] == "ssl"
|
||||
server = ldap3.Server(server_config["host"], port=server_config["port"],
|
||||
tls=tls, use_ssl=use_ssl, get_info=ldap3.ALL)
|
||||
server = ldap3.Server(
|
||||
server_config["host"],
|
||||
port=server_config["port"],
|
||||
tls=tls,
|
||||
use_ssl=use_ssl,
|
||||
get_info=ldap3.ALL,
|
||||
)
|
||||
|
||||
|
||||
# Main authentication/authorization function.
|
||||
@@ -40,14 +45,12 @@ def authenticate(username, password):
|
||||
return {"authenticated": False, "role": ""}
|
||||
|
||||
# Create the DN of the user
|
||||
dn = users_config["prefix"] + ldap3.utils.dn.escape_rdn(username) + \
|
||||
users_config["suffix"]
|
||||
dn = users_config["prefix"] + ldap3.utils.dn.escape_rdn(username) + users_config["suffix"]
|
||||
|
||||
# Bind to the server
|
||||
conn = ldap3.Connection(server, dn, password)
|
||||
if server_config["encryption"] == "starttls" and not conn.start_tls():
|
||||
print("ERROR: Couldn't issue STARTTLS to the LDAP server!",
|
||||
file=sys.stderr)
|
||||
print("ERROR: Couldn't issue STARTTLS to the LDAP server!", file=sys.stderr)
|
||||
return {"authenticated": False, "role": ""}
|
||||
if not conn.bind():
|
||||
return {"authenticated": False, "role": ""}
|
||||
@@ -56,25 +59,32 @@ def authenticate(username, password):
|
||||
if roles_config["root_dn"] != "":
|
||||
# search for role
|
||||
search_filter = "(&(objectclass={objclass})({attr}={value}))".format(
|
||||
objclass=roles_config["root_objectclass"],
|
||||
attr=roles_config["user_attribute"],
|
||||
value=ldap3.utils.conv.escape_filter_chars(dn))
|
||||
succ = conn.search(roles_config["root_dn"], search_filter,
|
||||
search_scope=ldap3.LEVEL,
|
||||
attributes=[roles_config["role_attribute"]])
|
||||
objclass=roles_config["root_objectclass"],
|
||||
attr=roles_config["user_attribute"],
|
||||
value=ldap3.utils.conv.escape_filter_chars(dn),
|
||||
)
|
||||
succ = conn.search(
|
||||
roles_config["root_dn"],
|
||||
search_filter,
|
||||
search_scope=ldap3.LEVEL,
|
||||
attributes=[roles_config["role_attribute"]],
|
||||
)
|
||||
if not succ or len(conn.entries) == 0:
|
||||
return {"authenticated": True, "role": ""}
|
||||
if len(conn.entries) > 1:
|
||||
roles = list(map(lambda x: x[roles_config["role_attribute"]].value,
|
||||
conn.entries))
|
||||
roles = list(map(lambda x: x[roles_config["role_attribute"]].value, conn.entries))
|
||||
# Because we don't know exactly which role the user should have
|
||||
# we authorize the user with an empty role.
|
||||
print("WARNING: Found more than one role for "
|
||||
"user '" + username + "':", ", ".join(roles) + "!",
|
||||
file=sys.stderr)
|
||||
print(
|
||||
"WARNING: Found more than one role for " "user '" + username + "':",
|
||||
", ".join(roles) + "!",
|
||||
file=sys.stderr,
|
||||
)
|
||||
return {"authenticated": True, "role": ""}
|
||||
return {"authenticated": True,
|
||||
"role": conn.entries[0][roles_config["role_attribute"]].value}
|
||||
return {
|
||||
"authenticated": True,
|
||||
"role": conn.entries[0][roles_config["role_attribute"]].value,
|
||||
}
|
||||
else:
|
||||
return {"authenticated": True, "role": ""}
|
||||
|
||||
|
||||
@@ -2,6 +2,10 @@ find_package(fmt REQUIRED)
|
||||
find_package(gflags REQUIRED)
|
||||
|
||||
set(communication_src_files
|
||||
websocket/auth.cpp
|
||||
websocket/server.cpp
|
||||
websocket/listener.cpp
|
||||
websocket/session.cpp
|
||||
bolt/v1/value.cpp
|
||||
buffer.cpp
|
||||
client.cpp
|
||||
@@ -9,8 +13,10 @@ set(communication_src_files
|
||||
helpers.cpp
|
||||
init.cpp)
|
||||
|
||||
find_package(Boost REQUIRED)
|
||||
|
||||
add_library(mg-communication STATIC ${communication_src_files})
|
||||
target_link_libraries(mg-communication Threads::Threads mg-utils mg-io fmt::fmt gflags)
|
||||
target_link_libraries(mg-communication Boost::headers Threads::Threads mg-utils mg-io mg-auth fmt::fmt gflags)
|
||||
|
||||
find_package(OpenSSL REQUIRED)
|
||||
target_link_libraries(mg-communication ${OPENSSL_LIBRARIES})
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
// Copyright 2021 Memgraph Ltd.
|
||||
// Copyright 2022 Memgraph Ltd.
|
||||
//
|
||||
// Use of this software is governed by the Business Source License
|
||||
// included in the file licenses/BSL.txt; by using this file, you agree to be bound by the terms of the Business Source
|
||||
@@ -21,7 +21,7 @@
|
||||
#include "utils/exceptions.hpp"
|
||||
#include "utils/logging.hpp"
|
||||
|
||||
namespace communication::bolt {
|
||||
namespace memgraph::communication::bolt {
|
||||
|
||||
/// This exception is thrown whenever an error occurs during query execution
|
||||
/// that isn't fatal (eg. mistyped query or some transient error occurred).
|
||||
@@ -315,4 +315,4 @@ class Client final {
|
||||
ChunkedEncoderBuffer<communication::ClientOutputStream> encoder_buffer_{output_stream_};
|
||||
ClientEncoder<ChunkedEncoderBuffer<communication::ClientOutputStream>> encoder_{encoder_buffer_};
|
||||
};
|
||||
} // namespace communication::bolt
|
||||
} // namespace memgraph::communication::bolt
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
// Copyright 2021 Memgraph Ltd.
|
||||
// Copyright 2022 Memgraph Ltd.
|
||||
//
|
||||
// Use of this software is governed by the Business Source License
|
||||
// included in the file licenses/BSL.txt; by using this file, you agree to be bound by the terms of the Business Source
|
||||
@@ -13,10 +13,10 @@
|
||||
|
||||
#include <cstdint>
|
||||
|
||||
namespace communication::bolt {
|
||||
namespace memgraph::communication::bolt {
|
||||
|
||||
static constexpr uint8_t kPreamble[4] = {0x60, 0x60, 0xB0, 0x17};
|
||||
static constexpr uint8_t kProtocol[4] = {0x00, 0x00, 0x00, 0x01};
|
||||
inline constexpr uint8_t kPreamble[4] = {0x60, 0x60, 0xB0, 0x17};
|
||||
inline constexpr uint8_t kProtocol[4] = {0x00, 0x00, 0x00, 0x01};
|
||||
|
||||
enum class Signature : uint8_t {
|
||||
Noop = 0x00,
|
||||
@@ -95,9 +95,9 @@ enum class Marker : uint8_t {
|
||||
Struct16 = 0xDD,
|
||||
};
|
||||
|
||||
static constexpr uint8_t MarkerString = 0, MarkerList = 1, MarkerMap = 2;
|
||||
static constexpr Marker MarkerTiny[3] = {Marker::TinyString, Marker::TinyList, Marker::TinyMap};
|
||||
static constexpr Marker Marker8[3] = {Marker::String8, Marker::List8, Marker::Map8};
|
||||
static constexpr Marker Marker16[3] = {Marker::String16, Marker::List16, Marker::Map16};
|
||||
static constexpr Marker Marker32[3] = {Marker::String32, Marker::List32, Marker::Map32};
|
||||
} // namespace communication::bolt
|
||||
inline constexpr uint8_t MarkerString = 0, MarkerList = 1, MarkerMap = 2;
|
||||
inline constexpr Marker MarkerTiny[3] = {Marker::TinyString, Marker::TinyList, Marker::TinyMap};
|
||||
inline constexpr Marker Marker8[3] = {Marker::String8, Marker::List8, Marker::Map8};
|
||||
inline constexpr Marker Marker16[3] = {Marker::String16, Marker::List16, Marker::Map16};
|
||||
inline constexpr Marker Marker32[3] = {Marker::String32, Marker::List32, Marker::Map32};
|
||||
} // namespace memgraph::communication::bolt
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
// Copyright 2021 Memgraph Ltd.
|
||||
// Copyright 2022 Memgraph Ltd.
|
||||
//
|
||||
// Use of this software is governed by the Business Source License
|
||||
// included in the file licenses/BSL.txt; by using this file, you agree to be bound by the terms of the Business Source
|
||||
@@ -14,22 +14,22 @@
|
||||
#include <cstddef>
|
||||
#include <cstdint>
|
||||
|
||||
namespace communication::bolt {
|
||||
namespace memgraph::communication::bolt {
|
||||
|
||||
/**
|
||||
* Sizes related to the chunk defined in Bolt protocol.
|
||||
*/
|
||||
static constexpr size_t kChunkHeaderSize = 2;
|
||||
static constexpr size_t kChunkMaxDataSize = 65535;
|
||||
static constexpr size_t kChunkWholeSize = kChunkHeaderSize + kChunkMaxDataSize;
|
||||
inline constexpr size_t kChunkHeaderSize = 2;
|
||||
inline constexpr size_t kChunkMaxDataSize = 65535;
|
||||
inline constexpr size_t kChunkWholeSize = kChunkHeaderSize + kChunkMaxDataSize;
|
||||
|
||||
/**
|
||||
* Handshake size defined in the Bolt protocol.
|
||||
*/
|
||||
static constexpr size_t kHandshakeSize = 20;
|
||||
inline constexpr size_t kHandshakeSize = 20;
|
||||
|
||||
static constexpr uint16_t kSupportedVersions[] = {0x0100, 0x0400, 0x0401, 0x0403};
|
||||
inline constexpr uint16_t kSupportedVersions[] = {0x0100, 0x0400, 0x0401, 0x0403};
|
||||
|
||||
static constexpr int kPullAll = -1;
|
||||
static constexpr int kPullLast = -1;
|
||||
} // namespace communication::bolt
|
||||
inline constexpr int kPullAll = -1;
|
||||
inline constexpr int kPullLast = -1;
|
||||
} // namespace memgraph::communication::bolt
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
// Copyright 2021 Memgraph Ltd.
|
||||
// Copyright 2022 Memgraph Ltd.
|
||||
//
|
||||
// Use of this software is governed by the Business Source License
|
||||
// included in the file licenses/BSL.txt; by using this file, you agree to be bound by the terms of the Business Source
|
||||
@@ -20,7 +20,7 @@
|
||||
|
||||
#include "communication/bolt/v1/constants.hpp"
|
||||
|
||||
namespace communication::bolt {
|
||||
namespace memgraph::communication::bolt {
|
||||
|
||||
/**
|
||||
* This class is used as the return value of the GetChunk function of the
|
||||
@@ -136,4 +136,4 @@ class ChunkedDecoderBuffer {
|
||||
std::vector<uint8_t> data_;
|
||||
size_t pos_{0};
|
||||
};
|
||||
} // namespace communication::bolt
|
||||
} // namespace memgraph::communication::bolt
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
// Copyright 2021 Memgraph Ltd.
|
||||
// Copyright 2022 Memgraph Ltd.
|
||||
//
|
||||
// Use of this software is governed by the Business Source License
|
||||
// included in the file licenses/BSL.txt; by using this file, you agree to be bound by the terms of the Business Source
|
||||
@@ -22,7 +22,7 @@
|
||||
#include "utils/logging.hpp"
|
||||
#include "utils/temporal.hpp"
|
||||
|
||||
namespace communication::bolt {
|
||||
namespace memgraph::communication::bolt {
|
||||
|
||||
/**
|
||||
* Bolt Decoder.
|
||||
@@ -591,4 +591,4 @@ class Decoder {
|
||||
return true;
|
||||
}
|
||||
};
|
||||
} // namespace communication::bolt
|
||||
} // namespace memgraph::communication::bolt
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
// Copyright 2021 Memgraph Ltd.
|
||||
// Copyright 2022 Memgraph Ltd.
|
||||
//
|
||||
// Use of this software is governed by the Business Source License
|
||||
// included in the file licenses/BSL.txt; by using this file, you agree to be bound by the terms of the Business Source
|
||||
@@ -22,7 +22,7 @@ static_assert(std::is_same_v<std::uint8_t, char> || std::is_same_v<std::uint8_t,
|
||||
"communication::bolt::Encoder requires uint8_t to be "
|
||||
"implemented as char or unsigned char.");
|
||||
|
||||
namespace communication::bolt {
|
||||
namespace memgraph::communication::bolt {
|
||||
|
||||
/**
|
||||
* Bolt BaseEncoder. Has public interfaces for writing Bolt encoded data.
|
||||
@@ -273,4 +273,4 @@ class BaseEncoder {
|
||||
}
|
||||
};
|
||||
|
||||
} // namespace communication::bolt
|
||||
} // namespace memgraph::communication::bolt
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
// Copyright 2021 Memgraph Ltd.
|
||||
// Copyright 2022 Memgraph Ltd.
|
||||
//
|
||||
// Use of this software is governed by the Business Source License
|
||||
// included in the file licenses/BSL.txt; by using this file, you agree to be bound by the terms of the Business Source
|
||||
@@ -18,7 +18,7 @@
|
||||
|
||||
#include "communication/bolt/v1/constants.hpp"
|
||||
|
||||
namespace communication::bolt {
|
||||
namespace memgraph::communication::bolt {
|
||||
|
||||
/**
|
||||
* @brief ChunkedEncoderBuffer
|
||||
@@ -123,4 +123,4 @@ class ChunkedEncoderBuffer {
|
||||
// Amount of data in chunk array.
|
||||
size_t have_{0};
|
||||
};
|
||||
} // namespace communication::bolt
|
||||
} // namespace memgraph::communication::bolt
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
// Copyright 2021 Memgraph Ltd.
|
||||
// Copyright 2022 Memgraph Ltd.
|
||||
//
|
||||
// Use of this software is governed by the Business Source License
|
||||
// included in the file licenses/BSL.txt; by using this file, you agree to be bound by the terms of the Business Source
|
||||
@@ -14,7 +14,7 @@
|
||||
#include "communication/bolt/v1/codes.hpp"
|
||||
#include "communication/bolt/v1/encoder/base_encoder.hpp"
|
||||
|
||||
namespace communication::bolt {
|
||||
namespace memgraph::communication::bolt {
|
||||
|
||||
/**
|
||||
* Bolt Client Encoder.
|
||||
@@ -169,4 +169,4 @@ class ClientEncoder : private BaseEncoder<Buffer> {
|
||||
return buffer_.Flush();
|
||||
}
|
||||
};
|
||||
} // namespace communication::bolt
|
||||
} // namespace memgraph::communication::bolt
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
// Copyright 2021 Memgraph Ltd.
|
||||
// Copyright 2022 Memgraph Ltd.
|
||||
//
|
||||
// Use of this software is governed by the Business Source License
|
||||
// included in the file licenses/BSL.txt; by using this file, you agree to be bound by the terms of the Business Source
|
||||
@@ -14,7 +14,7 @@
|
||||
#include "communication/bolt/v1/codes.hpp"
|
||||
#include "communication/bolt/v1/encoder/base_encoder.hpp"
|
||||
|
||||
namespace communication::bolt {
|
||||
namespace memgraph::communication::bolt {
|
||||
|
||||
/**
|
||||
* Bolt Encoder.
|
||||
@@ -158,4 +158,4 @@ class Encoder : private BaseEncoder<Buffer> {
|
||||
return buffer_.Flush();
|
||||
}
|
||||
};
|
||||
} // namespace communication::bolt
|
||||
} // namespace memgraph::communication::bolt
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
// Copyright 2021 Memgraph Ltd.
|
||||
// Copyright 2022 Memgraph Ltd.
|
||||
//
|
||||
// Use of this software is governed by the Business Source License
|
||||
// included in the file licenses/BSL.txt; by using this file, you agree to be bound by the terms of the Business Source
|
||||
@@ -17,7 +17,7 @@
|
||||
|
||||
#include "utils/exceptions.hpp"
|
||||
|
||||
namespace communication::bolt {
|
||||
namespace memgraph::communication::bolt {
|
||||
|
||||
/**
|
||||
* Used to indicate something is wrong with the client but the transaction is
|
||||
@@ -83,4 +83,4 @@ class VerboseError : public utils::BasicException {
|
||||
std::string code_;
|
||||
};
|
||||
|
||||
} // namespace communication::bolt
|
||||
} // namespace memgraph::communication::bolt
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
// Copyright 2021 Memgraph Ltd.
|
||||
// Copyright 2022 Memgraph Ltd.
|
||||
//
|
||||
// Use of this software is governed by the Business Source License
|
||||
// included in the file licenses/BSL.txt; by using this file, you agree to be bound by the terms of the Business Source
|
||||
@@ -27,7 +27,7 @@
|
||||
#include "utils/exceptions.hpp"
|
||||
#include "utils/logging.hpp"
|
||||
|
||||
namespace communication::bolt {
|
||||
namespace memgraph::communication::bolt {
|
||||
|
||||
/**
|
||||
* Bolt Session Exception
|
||||
@@ -195,4 +195,4 @@ class Session {
|
||||
}
|
||||
};
|
||||
|
||||
} // namespace communication::bolt
|
||||
} // namespace memgraph::communication::bolt
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
// Copyright 2021 Memgraph Ltd.
|
||||
// Copyright 2022 Memgraph Ltd.
|
||||
//
|
||||
// Use of this software is governed by the Business Source License
|
||||
// included in the file licenses/BSL.txt; by using this file, you agree to be bound by the terms of the Business Source
|
||||
@@ -13,7 +13,7 @@
|
||||
|
||||
#include <cstdint>
|
||||
|
||||
namespace communication::bolt {
|
||||
namespace memgraph::communication::bolt {
|
||||
|
||||
/**
|
||||
* This class represents states in execution of the Bolt protocol.
|
||||
@@ -55,4 +55,4 @@ enum class State : uint8_t {
|
||||
*/
|
||||
Close
|
||||
};
|
||||
} // namespace communication::bolt
|
||||
} // namespace memgraph::communication::bolt
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
// Copyright 2021 Memgraph Ltd.
|
||||
// Copyright 2022 Memgraph Ltd.
|
||||
//
|
||||
// Use of this software is governed by the Business Source License
|
||||
// included in the file licenses/BSL.txt; by using this file, you agree to be bound by the terms of the Business Source
|
||||
@@ -20,7 +20,7 @@
|
||||
#include "utils/likely.hpp"
|
||||
#include "utils/logging.hpp"
|
||||
|
||||
namespace communication::bolt {
|
||||
namespace memgraph::communication::bolt {
|
||||
|
||||
/**
|
||||
* Error state run function
|
||||
@@ -95,4 +95,4 @@ State StateErrorRun(TSession &session, State state) {
|
||||
return state;
|
||||
}
|
||||
}
|
||||
} // namespace communication::bolt
|
||||
} // namespace memgraph::communication::bolt
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
// Copyright 2021 Memgraph Ltd.
|
||||
// Copyright 2022 Memgraph Ltd.
|
||||
//
|
||||
// Use of this software is governed by the Business Source License
|
||||
// included in the file licenses/BSL.txt; by using this file, you agree to be bound by the terms of the Business Source
|
||||
@@ -26,7 +26,7 @@
|
||||
#include "utils/logging.hpp"
|
||||
#include "utils/message.hpp"
|
||||
|
||||
namespace communication::bolt {
|
||||
namespace memgraph::communication::bolt {
|
||||
|
||||
template <typename TSession>
|
||||
State RunHandlerV1(Signature signature, TSession &session, State state, Marker marker) {
|
||||
@@ -118,4 +118,4 @@ State StateExecutingRun(TSession &session, State state) {
|
||||
return State::Close;
|
||||
}
|
||||
}
|
||||
} // namespace communication::bolt
|
||||
} // namespace memgraph::communication::bolt
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
// Copyright 2021 Memgraph Ltd.
|
||||
// Copyright 2022 Memgraph Ltd.
|
||||
//
|
||||
// Use of this software is governed by the Business Source License
|
||||
// included in the file licenses/BSL.txt; by using this file, you agree to be bound by the terms of the Business Source
|
||||
@@ -24,7 +24,7 @@
|
||||
#include "utils/logging.hpp"
|
||||
#include "utils/message.hpp"
|
||||
|
||||
namespace communication::bolt {
|
||||
namespace memgraph::communication::bolt {
|
||||
// TODO: Revise these error messages
|
||||
inline std::pair<std::string, std::string> ExceptionToErrorMessage(const std::exception &e) {
|
||||
if (const auto *verbose = dynamic_cast<const VerboseError *>(&e)) {
|
||||
@@ -415,4 +415,4 @@ State HandleRoute(TSession &session) {
|
||||
}
|
||||
return State::Error;
|
||||
}
|
||||
} // namespace communication::bolt
|
||||
} // namespace memgraph::communication::bolt
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
// Copyright 2021 Memgraph Ltd.
|
||||
// Copyright 2022 Memgraph Ltd.
|
||||
//
|
||||
// Use of this software is governed by the Business Source License
|
||||
// included in the file licenses/BSL.txt; by using this file, you agree to be bound by the terms of the Business Source
|
||||
@@ -22,7 +22,7 @@
|
||||
#include "utils/likely.hpp"
|
||||
#include "utils/logging.hpp"
|
||||
|
||||
namespace communication::bolt {
|
||||
namespace memgraph::communication::bolt {
|
||||
|
||||
inline bool CopyProtocolInformationIfSupported(uint16_t version, uint8_t *protocol) {
|
||||
const auto *supported_version = std::find(std::begin(kSupportedVersions), std::end(kSupportedVersions), version);
|
||||
@@ -110,4 +110,4 @@ State StateHandshakeRun(TSession &session) {
|
||||
|
||||
return State::Init;
|
||||
}
|
||||
} // namespace communication::bolt
|
||||
} // namespace memgraph::communication::bolt
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
// Copyright 2021 Memgraph Ltd.
|
||||
// Copyright 2022 Memgraph Ltd.
|
||||
//
|
||||
// Use of this software is governed by the Business Source License
|
||||
// included in the file licenses/BSL.txt; by using this file, you agree to be bound by the terms of the Business Source
|
||||
@@ -21,7 +21,7 @@
|
||||
#include "utils/likely.hpp"
|
||||
#include "utils/logging.hpp"
|
||||
|
||||
namespace communication::bolt {
|
||||
namespace memgraph::communication::bolt {
|
||||
|
||||
namespace details {
|
||||
template <typename TSession>
|
||||
@@ -212,4 +212,4 @@ State StateInitRun(TSession &session) {
|
||||
spdlog::trace("Unsupported bolt version:{}.{})!", session.version_.major, session.version_.minor);
|
||||
return State::Close;
|
||||
}
|
||||
} // namespace communication::bolt
|
||||
} // namespace memgraph::communication::bolt
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
// Copyright 2021 Memgraph Ltd.
|
||||
// Copyright 2022 Memgraph Ltd.
|
||||
//
|
||||
// Use of this software is governed by the Business Source License
|
||||
// included in the file licenses/BSL.txt; by using this file, you agree to be bound by the terms of the Business Source
|
||||
@@ -14,7 +14,7 @@
|
||||
#include "utils/algorithm.hpp"
|
||||
#include "utils/string.hpp"
|
||||
|
||||
namespace communication::bolt {
|
||||
namespace memgraph::communication::bolt {
|
||||
|
||||
#define DEF_GETTER_BY_VAL(type, value_type, field) \
|
||||
value_type &Value::Value##type() { \
|
||||
@@ -461,4 +461,4 @@ std::ostream &operator<<(std::ostream &os, const Value::Type type) {
|
||||
return os << "duration";
|
||||
}
|
||||
}
|
||||
} // namespace communication::bolt
|
||||
} // namespace memgraph::communication::bolt
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
// Copyright 2021 Memgraph Ltd.
|
||||
// Copyright 2022 Memgraph Ltd.
|
||||
//
|
||||
// Use of this software is governed by the Business Source License
|
||||
// included in the file licenses/BSL.txt; by using this file, you agree to be bound by the terms of the Business Source
|
||||
@@ -20,7 +20,7 @@
|
||||
#include "utils/exceptions.hpp"
|
||||
#include "utils/temporal.hpp"
|
||||
|
||||
namespace communication::bolt {
|
||||
namespace memgraph::communication::bolt {
|
||||
|
||||
/** Forward declaration of Value class. */
|
||||
class Value;
|
||||
@@ -282,4 +282,4 @@ std::ostream &operator<<(std::ostream &os, const UnboundedEdge &edge);
|
||||
std::ostream &operator<<(std::ostream &os, const Path &path);
|
||||
std::ostream &operator<<(std::ostream &os, const Value &value);
|
||||
std::ostream &operator<<(std::ostream &os, const Value::Type type);
|
||||
} // namespace communication::bolt
|
||||
} // namespace memgraph::communication::bolt
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
// Copyright 2021 Memgraph Ltd.
|
||||
// Copyright 2022 Memgraph Ltd.
|
||||
//
|
||||
// Use of this software is governed by the Business Source License
|
||||
// included in the file licenses/BSL.txt; by using this file, you agree to be bound by the terms of the Business Source
|
||||
@@ -13,7 +13,7 @@
|
||||
|
||||
#include "utils/logging.hpp"
|
||||
|
||||
namespace communication {
|
||||
namespace memgraph::communication {
|
||||
|
||||
Buffer::Buffer() : data_(kBufferInitialSize, 0), read_end_(this), write_end_(this) {}
|
||||
|
||||
@@ -77,4 +77,4 @@ void Buffer::Resize(size_t len) {
|
||||
|
||||
void Buffer::Clear() { have_ = 0; }
|
||||
|
||||
} // namespace communication
|
||||
} // namespace memgraph::communication
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
// Copyright 2021 Memgraph Ltd.
|
||||
// Copyright 2022 Memgraph Ltd.
|
||||
//
|
||||
// Use of this software is governed by the Business Source License
|
||||
// included in the file licenses/BSL.txt; by using this file, you agree to be bound by the terms of the Business Source
|
||||
@@ -15,7 +15,7 @@
|
||||
|
||||
#include "io/network/stream_buffer.hpp"
|
||||
|
||||
namespace communication {
|
||||
namespace memgraph::communication {
|
||||
|
||||
/**
|
||||
* @brief Buffer
|
||||
@@ -171,4 +171,4 @@ class Buffer final {
|
||||
ReadEnd read_end_;
|
||||
WriteEnd write_end_;
|
||||
};
|
||||
} // namespace communication
|
||||
} // namespace memgraph::communication
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
// Copyright 2021 Memgraph Ltd.
|
||||
// Copyright 2022 Memgraph Ltd.
|
||||
//
|
||||
// Use of this software is governed by the Business Source License
|
||||
// included in the file licenses/BSL.txt; by using this file, you agree to be bound by the terms of the Business Source
|
||||
@@ -14,7 +14,7 @@
|
||||
#include "communication/helpers.hpp"
|
||||
#include "utils/logging.hpp"
|
||||
|
||||
namespace communication {
|
||||
namespace memgraph::communication {
|
||||
|
||||
Client::Client(ClientContext *context) : context_(context) {}
|
||||
|
||||
@@ -239,4 +239,4 @@ bool ClientOutputStream::Write(const uint8_t *data, size_t len, bool have_more)
|
||||
}
|
||||
bool ClientOutputStream::Write(const std::string &str, bool have_more) { return client_.Write(str, have_more); }
|
||||
|
||||
} // namespace communication
|
||||
} // namespace memgraph::communication
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
// Copyright 2021 Memgraph Ltd.
|
||||
// Copyright 2022 Memgraph Ltd.
|
||||
//
|
||||
// Use of this software is governed by the Business Source License
|
||||
// included in the file licenses/BSL.txt; by using this file, you agree to be bound by the terms of the Business Source
|
||||
@@ -21,14 +21,14 @@
|
||||
#include "io/network/endpoint.hpp"
|
||||
#include "io/network/socket.hpp"
|
||||
|
||||
namespace communication {
|
||||
namespace memgraph::communication {
|
||||
|
||||
/**
|
||||
* This class implements a generic network Client.
|
||||
* It uses blocking sockets and provides an API that can be used to receive/send
|
||||
* data over the network connection.
|
||||
*
|
||||
* NOTE: If you use this client you **must** create `communication::SSLInit`
|
||||
* NOTE: If you use this client you **must** create `memgraph::communication::SSLInit`
|
||||
* from the `main` function before using the client!
|
||||
*/
|
||||
class Client final {
|
||||
@@ -167,4 +167,4 @@ class ClientOutputStream final {
|
||||
Client &client_;
|
||||
};
|
||||
|
||||
} // namespace communication
|
||||
} // namespace memgraph::communication
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
// Copyright 2021 Memgraph Ltd.
|
||||
// Copyright 2022 Memgraph Ltd.
|
||||
//
|
||||
// Use of this software is governed by the Business Source License
|
||||
// included in the file licenses/BSL.txt; by using this file, you agree to be bound by the terms of the Business Source
|
||||
@@ -10,10 +10,13 @@
|
||||
// licenses/APL.txt.
|
||||
|
||||
#include "communication/context.hpp"
|
||||
#include <boost/asio/ssl/context.hpp>
|
||||
#include <boost/asio/ssl/verify_mode.hpp>
|
||||
#include <boost/system/detail/error_code.hpp>
|
||||
|
||||
#include "utils/logging.hpp"
|
||||
|
||||
namespace communication {
|
||||
namespace memgraph::communication {
|
||||
|
||||
ClientContext::ClientContext(bool use_ssl) : use_ssl_(use_ssl), ctx_(nullptr) {
|
||||
if (use_ssl_) {
|
||||
@@ -73,80 +76,66 @@ SSL_CTX *ClientContext::context() { return ctx_; }
|
||||
|
||||
bool ClientContext::use_ssl() { return use_ssl_; }
|
||||
|
||||
ServerContext::ServerContext() : use_ssl_(false), ctx_(nullptr) {}
|
||||
|
||||
ServerContext::ServerContext(const std::string &key_file, const std::string &cert_file, const std::string &ca_file,
|
||||
bool verify_peer)
|
||||
: use_ssl_(true),
|
||||
#if OPENSSL_VERSION_NUMBER < 0x10100000L
|
||||
ctx_(SSL_CTX_new(SSLv23_server_method()))
|
||||
#else
|
||||
ctx_(SSL_CTX_new(TLS_server_method()))
|
||||
#endif
|
||||
{
|
||||
// TODO (mferencevic): add support for encrypted private keys
|
||||
// TODO (mferencevic): add certificate revocation list (CRL)
|
||||
MG_ASSERT(SSL_CTX_use_certificate_file(ctx_, cert_file.c_str(), SSL_FILETYPE_PEM) == 1,
|
||||
"Couldn't load server certificate from file: {}", cert_file);
|
||||
MG_ASSERT(SSL_CTX_use_PrivateKey_file(ctx_, key_file.c_str(), SSL_FILETYPE_PEM) == 1,
|
||||
"Couldn't load server private key from file: {}", key_file);
|
||||
bool verify_peer) {
|
||||
namespace ssl = boost::asio::ssl;
|
||||
ctx_.emplace(ssl::context::tls_server);
|
||||
// NOLINTNEXTLINE(hicpp-signed-bitwise)
|
||||
ctx_->set_options(ssl::context::default_workarounds | ssl::context::no_sslv2 | ssl::context::no_sslv3 |
|
||||
ssl::context::single_dh_use);
|
||||
ctx_->set_default_verify_paths();
|
||||
// TODO: add support for encrypted private keys
|
||||
// TODO: add certificate revocation list (CRL)
|
||||
boost::system::error_code ec;
|
||||
ctx_->use_certificate_chain_file(cert_file, ec);
|
||||
MG_ASSERT(!ec, "Couldn't load server certificate from file: {}", cert_file);
|
||||
ctx_->use_private_key_file(key_file, ssl::context::pem, ec);
|
||||
MG_ASSERT(!ec, "Couldn't load server private key from file: {}", key_file);
|
||||
|
||||
// Disable legacy SSL support. Other options can be seen here:
|
||||
// https://www.openssl.org/docs/man1.0.2/ssl/SSL_CTX_set_options.html
|
||||
SSL_CTX_set_options(ctx_, SSL_OP_NO_SSLv3);
|
||||
ctx_->set_options(SSL_OP_NO_SSLv3, ec);
|
||||
MG_ASSERT(!ec, "Setting options to SSL context failed!");
|
||||
|
||||
if (ca_file != "") {
|
||||
if (!ca_file.empty()) {
|
||||
// Load the certificate authority file.
|
||||
MG_ASSERT(SSL_CTX_load_verify_locations(ctx_, ca_file.c_str(), nullptr) == 1,
|
||||
"Couldn't load certificate authority from file: {}", ca_file);
|
||||
boost::system::error_code ec;
|
||||
ctx_->load_verify_file(ca_file, ec);
|
||||
MG_ASSERT(!ec, "Couldn't load certificate authority from file: {}", ca_file);
|
||||
|
||||
if (verify_peer) {
|
||||
// Add the CA to list of accepted CAs that is sent to the client.
|
||||
STACK_OF(X509_NAME) *ca_names = SSL_load_client_CA_file(ca_file.c_str());
|
||||
MG_ASSERT(ca_names != nullptr, "Couldn't load certificate authority from file: {}", ca_file);
|
||||
// `ca_names` doesn' need to be free'd because we pass it to
|
||||
// `SSL_CTX_set_client_CA_list`:
|
||||
// https://mta.openssl.org/pipermail/openssl-users/2015-May/001363.html
|
||||
SSL_CTX_set_client_CA_list(ctx_, ca_names);
|
||||
|
||||
// Enable verification of the client certificate.
|
||||
SSL_CTX_set_verify(ctx_, SSL_VERIFY_PEER | SSL_VERIFY_FAIL_IF_NO_PEER_CERT, nullptr);
|
||||
// NOLINTNEXTLINE(hicpp-signed-bitwise)
|
||||
ctx_->set_verify_mode(ssl::verify_peer | ssl::verify_fail_if_no_peer_cert, ec);
|
||||
MG_ASSERT(!ec, "Setting SSL verification mode failed!");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
ServerContext::ServerContext(ServerContext &&other) noexcept : use_ssl_(other.use_ssl_), ctx_(other.ctx_) {
|
||||
other.use_ssl_ = false;
|
||||
other.ctx_ = nullptr;
|
||||
}
|
||||
ServerContext::ServerContext(ServerContext &&other) noexcept { std::swap(ctx_, other.ctx_); }
|
||||
|
||||
ServerContext &ServerContext::operator=(ServerContext &&other) noexcept {
|
||||
if (this == &other) return *this;
|
||||
|
||||
// destroy my objects
|
||||
if (use_ssl_) {
|
||||
SSL_CTX_free(ctx_);
|
||||
}
|
||||
|
||||
// move other objects to self
|
||||
use_ssl_ = other.use_ssl_;
|
||||
ctx_ = other.ctx_;
|
||||
ctx_ = std::move(other.ctx_);
|
||||
|
||||
// reset other objects
|
||||
other.use_ssl_ = false;
|
||||
other.ctx_ = nullptr;
|
||||
other.ctx_.reset();
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
ServerContext::~ServerContext() {
|
||||
if (use_ssl_) {
|
||||
SSL_CTX_free(ctx_);
|
||||
}
|
||||
ServerContext::~ServerContext() {}
|
||||
|
||||
SSL_CTX *ServerContext::context() {
|
||||
MG_ASSERT(ctx_);
|
||||
return ctx_->native_handle();
|
||||
}
|
||||
|
||||
SSL_CTX *ServerContext::context() { return ctx_; }
|
||||
boost::asio::ssl::context &ServerContext::context_clone() {
|
||||
MG_ASSERT(ctx_);
|
||||
return *ctx_;
|
||||
}
|
||||
|
||||
bool ServerContext::use_ssl() { return use_ssl_; }
|
||||
bool ServerContext::use_ssl() const { return ctx_.has_value(); }
|
||||
|
||||
} // namespace communication
|
||||
} // namespace memgraph::communication
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
// Copyright 2021 Memgraph Ltd.
|
||||
// Copyright 2022 Memgraph Ltd.
|
||||
//
|
||||
// Use of this software is governed by the Business Source License
|
||||
// included in the file licenses/BSL.txt; by using this file, you agree to be bound by the terms of the Business Source
|
||||
@@ -11,11 +11,13 @@
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <optional>
|
||||
#include <string>
|
||||
|
||||
#include <openssl/ssl.h>
|
||||
#include <boost/asio/ssl/context.hpp>
|
||||
|
||||
namespace communication {
|
||||
namespace memgraph::communication {
|
||||
|
||||
/**
|
||||
* This class represents a context that should be used with network clients. One
|
||||
@@ -69,11 +71,7 @@ class ClientContext final {
|
||||
*/
|
||||
class ServerContext final {
|
||||
public:
|
||||
/**
|
||||
* This constructor constructs a ServerContext that doesn't use SSL.
|
||||
*/
|
||||
ServerContext();
|
||||
|
||||
ServerContext() = default;
|
||||
/**
|
||||
* This constructor constructs a ServerContext that uses SSL. The parameters
|
||||
* `key_file` and `cert_file` can't be "" because when setting up a server it
|
||||
@@ -95,16 +93,15 @@ class ServerContext final {
|
||||
ServerContext(ServerContext &&other) noexcept;
|
||||
ServerContext &operator=(ServerContext &&other) noexcept;
|
||||
|
||||
// Destructor that handles ownership of the SSL object.
|
||||
~ServerContext();
|
||||
|
||||
SSL_CTX *context();
|
||||
boost::asio::ssl::context &context_clone();
|
||||
|
||||
bool use_ssl();
|
||||
bool use_ssl() const;
|
||||
|
||||
private:
|
||||
bool use_ssl_;
|
||||
SSL_CTX *ctx_;
|
||||
std::optional<boost::asio::ssl::context> ctx_;
|
||||
};
|
||||
|
||||
} // namespace communication
|
||||
} // namespace memgraph::communication
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
// Copyright 2021 Memgraph Ltd.
|
||||
// Copyright 2022 Memgraph Ltd.
|
||||
//
|
||||
// Use of this software is governed by the Business Source License
|
||||
// included in the file licenses/BSL.txt; by using this file, you agree to be bound by the terms of the Business Source
|
||||
@@ -13,7 +13,7 @@
|
||||
|
||||
#include "utils/exceptions.hpp"
|
||||
|
||||
namespace communication {
|
||||
namespace memgraph::communication {
|
||||
|
||||
/**
|
||||
* This exception is thrown to indicate to the communication stack that the
|
||||
@@ -22,4 +22,4 @@ namespace communication {
|
||||
class SessionClosedException : public utils::BasicException {
|
||||
using utils::BasicException::BasicException;
|
||||
};
|
||||
} // namespace communication
|
||||
} // namespace memgraph::communication
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
// Copyright 2021 Memgraph Ltd.
|
||||
// Copyright 2022 Memgraph Ltd.
|
||||
//
|
||||
// Use of this software is governed by the Business Source License
|
||||
// included in the file licenses/BSL.txt; by using this file, you agree to be bound by the terms of the Business Source
|
||||
@@ -13,7 +13,7 @@
|
||||
|
||||
#include "communication/helpers.hpp"
|
||||
|
||||
namespace communication {
|
||||
namespace memgraph::communication {
|
||||
|
||||
const std::string SslGetLastError() {
|
||||
char buff[2048];
|
||||
@@ -21,4 +21,4 @@ const std::string SslGetLastError() {
|
||||
ERR_error_string_n(err, buff, sizeof(buff));
|
||||
return std::string(buff);
|
||||
}
|
||||
} // namespace communication
|
||||
} // namespace memgraph::communication
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
// Copyright 2021 Memgraph Ltd.
|
||||
// Copyright 2022 Memgraph Ltd.
|
||||
//
|
||||
// Use of this software is governed by the Business Source License
|
||||
// included in the file licenses/BSL.txt; by using this file, you agree to be bound by the terms of the Business Source
|
||||
@@ -13,11 +13,11 @@
|
||||
|
||||
#include <string>
|
||||
|
||||
namespace communication {
|
||||
namespace memgraph::communication {
|
||||
|
||||
/**
|
||||
* This function reads and returns a string describing the last OpenSSL error.
|
||||
*/
|
||||
const std::string SslGetLastError();
|
||||
|
||||
} // namespace communication
|
||||
} // namespace memgraph::communication
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
// Copyright 2021 Memgraph Ltd.
|
||||
// Copyright 2022 Memgraph Ltd.
|
||||
//
|
||||
// Use of this software is governed by the Business Source License
|
||||
// included in the file licenses/BSL.txt; by using this file, you agree to be bound by the terms of the Business Source
|
||||
@@ -20,7 +20,7 @@
|
||||
#include "utils/signals.hpp"
|
||||
#include "utils/spin_lock.hpp"
|
||||
|
||||
namespace communication {
|
||||
namespace memgraph::communication {
|
||||
|
||||
namespace {
|
||||
// OpenSSL before 1.1 did not have a out-of-the-box multithreading support
|
||||
@@ -72,4 +72,4 @@ SSLInit::SSLInit() {
|
||||
}
|
||||
|
||||
SSLInit::~SSLInit() { Cleanup(); }
|
||||
} // namespace communication
|
||||
} // namespace memgraph::communication
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
// Copyright 2021 Memgraph Ltd.
|
||||
// Copyright 2022 Memgraph Ltd.
|
||||
//
|
||||
// Use of this software is governed by the Business Source License
|
||||
// included in the file licenses/BSL.txt; by using this file, you agree to be bound by the terms of the Business Source
|
||||
@@ -11,7 +11,7 @@
|
||||
|
||||
#pragma once
|
||||
|
||||
namespace communication {
|
||||
namespace memgraph::communication {
|
||||
|
||||
/**
|
||||
* Create this object in each `main` file that uses the Communication stack. It
|
||||
@@ -36,4 +36,4 @@ struct SSLInit {
|
||||
~SSLInit();
|
||||
};
|
||||
|
||||
} // namespace communication
|
||||
} // namespace memgraph::communication
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user