Compare commits
10 Commits
T610-FL-Ad
...
MG-pmr-pro
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
c8769fa677 | ||
|
|
16245d7ec8 | ||
|
|
0feeae443c | ||
|
|
5338ef5750 | ||
|
|
49ad114366 | ||
|
|
77c8a650fa | ||
|
|
e27485388d | ||
|
|
51b5d81018 | ||
|
|
10cc0c01d2 | ||
|
|
45cd78a435 |
@@ -1,7 +1,6 @@
|
|||||||
---
|
---
|
||||||
Checks: '*,
|
Checks: '*,
|
||||||
-abseil-string-find-str-contains,
|
-abseil-string-find-str-contains,
|
||||||
-altera-id-dependent-backward-branch,
|
|
||||||
-altera-struct-pack-align,
|
-altera-struct-pack-align,
|
||||||
-altera-unroll-loops,
|
-altera-unroll-loops,
|
||||||
-android-*,
|
-android-*,
|
||||||
@@ -61,9 +60,7 @@ Checks: '*,
|
|||||||
-readability-magic-numbers,
|
-readability-magic-numbers,
|
||||||
-readability-named-parameter,
|
-readability-named-parameter,
|
||||||
-misc-no-recursion,
|
-misc-no-recursion,
|
||||||
-concurrency-mt-unsafe,
|
-concurrency-mt-unsafe'
|
||||||
-bugprone-easily-swappable-parameters'
|
|
||||||
|
|
||||||
WarningsAsErrors: ''
|
WarningsAsErrors: ''
|
||||||
HeaderFilterRegex: 'src/.*'
|
HeaderFilterRegex: 'src/.*'
|
||||||
AnalyzeTemporaryDtors: false
|
AnalyzeTemporaryDtors: false
|
||||||
@@ -90,3 +87,4 @@ CheckOptions:
|
|||||||
- key: modernize-use-nullptr.NullMacros
|
- key: modernize-use-nullptr.NullMacros
|
||||||
value: 'NULL'
|
value: 'NULL'
|
||||||
...
|
...
|
||||||
|
|
||||||
|
|||||||
@@ -16,7 +16,6 @@ tmpdir=$(mktemp -d repo-XXXXXXXX)
|
|||||||
trap "rm -rf $tmpdir" EXIT INT
|
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")
|
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
|
for file in $modified_files; do
|
||||||
echo "Checking $file..."
|
echo "Checking $file..."
|
||||||
|
|
||||||
@@ -24,13 +23,21 @@ for file in $modified_files; do
|
|||||||
|
|
||||||
git checkout-index --prefix="$tmpdir/" -- $file
|
git checkout-index --prefix="$tmpdir/" -- $file
|
||||||
|
|
||||||
# Do not break header checker
|
echo "Running clang-format..."
|
||||||
|
$project_folder/tools/git-clang-format $tmpdir/$file
|
||||||
|
code=$?
|
||||||
|
|
||||||
|
if [ $code -ne 0 ]; then
|
||||||
|
break
|
||||||
|
fi
|
||||||
|
|
||||||
echo "Running header checker..."
|
echo "Running header checker..."
|
||||||
$project_folder/tools/header-checker.py $tmpdir/$file $file --amend-year
|
$project_folder/tools/header-checker.py $tmpdir/$file $file --amend-year
|
||||||
CODE=$?
|
code=$?
|
||||||
if [ $CODE -ne 0 ]; then
|
|
||||||
FAIL=1
|
if [ $code -ne 0 ]; then
|
||||||
|
break
|
||||||
fi
|
fi
|
||||||
done;
|
done;
|
||||||
|
|
||||||
return ${FAIL}
|
return $code
|
||||||
|
|||||||
5
.github/workflows/diff.yaml
vendored
5
.github/workflows/diff.yaml
vendored
@@ -1,7 +1,4 @@
|
|||||||
name: Diff
|
name: Diff
|
||||||
concurrency:
|
|
||||||
group: ${{ github.head_ref || github.sha }}
|
|
||||||
cancel-in-progress: true
|
|
||||||
|
|
||||||
on:
|
on:
|
||||||
push:
|
push:
|
||||||
@@ -115,7 +112,7 @@ jobs:
|
|||||||
source /opt/toolchain-v4/activate
|
source /opt/toolchain-v4/activate
|
||||||
|
|
||||||
# Restrict clang-tidy results only to the modified parts
|
# Restrict clang-tidy results only to the modified parts
|
||||||
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
|
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
|
||||||
|
|
||||||
# Fail if any warning is reported
|
# Fail if any warning is reported
|
||||||
! cat ./build/clang_tidy_output.txt | ./tools/github/clang-tidy/grep_error_lines.sh > /dev/null
|
! cat ./build/clang_tidy_output.txt | ./tools/github/clang-tidy/grep_error_lines.sh > /dev/null
|
||||||
|
|||||||
74
.github/workflows/package_all.yaml
vendored
74
.github/workflows/package_all.yaml
vendored
@@ -6,11 +6,11 @@ on: workflow_dispatch
|
|||||||
|
|
||||||
jobs:
|
jobs:
|
||||||
centos-7:
|
centos-7:
|
||||||
runs-on: [self-hosted, DockerMgBuild, X64]
|
runs-on: [self-hosted, DockerMgBuild]
|
||||||
timeout-minutes: 60
|
timeout-minutes: 60
|
||||||
steps:
|
steps:
|
||||||
- name: "Set up repository"
|
- name: "Set up repository"
|
||||||
uses: actions/checkout@v3
|
uses: actions/checkout@v2
|
||||||
with:
|
with:
|
||||||
fetch-depth: 0 # Required because of release/get_version.py
|
fetch-depth: 0 # Required because of release/get_version.py
|
||||||
- name: "Build package"
|
- name: "Build package"
|
||||||
@@ -22,29 +22,29 @@ jobs:
|
|||||||
name: centos-7
|
name: centos-7
|
||||||
path: build/output/centos-7/memgraph*.rpm
|
path: build/output/centos-7/memgraph*.rpm
|
||||||
|
|
||||||
centos-9:
|
centos-8:
|
||||||
runs-on: [self-hosted, DockerMgBuild, X64]
|
runs-on: [self-hosted, DockerMgBuild]
|
||||||
timeout-minutes: 60
|
timeout-minutes: 60
|
||||||
steps:
|
steps:
|
||||||
- name: "Set up repository"
|
- name: "Set up repository"
|
||||||
uses: actions/checkout@v3
|
uses: actions/checkout@v2
|
||||||
with:
|
with:
|
||||||
fetch-depth: 0 # Required because of release/get_version.py
|
fetch-depth: 0 # Required because of release/get_version.py
|
||||||
- name: "Build package"
|
- name: "Build package"
|
||||||
run: |
|
run: |
|
||||||
./release/package/run.sh package centos-9
|
./release/package/run.sh package centos-8
|
||||||
- name: "Upload package"
|
- name: "Upload package"
|
||||||
uses: actions/upload-artifact@v2
|
uses: actions/upload-artifact@v2
|
||||||
with:
|
with:
|
||||||
name: centos-9
|
name: centos-8
|
||||||
path: build/output/centos-9/memgraph*.rpm
|
path: build/output/centos-8/memgraph*.rpm
|
||||||
|
|
||||||
debian-10:
|
debian-10:
|
||||||
runs-on: [self-hosted, DockerMgBuild, X64]
|
runs-on: [self-hosted, DockerMgBuild]
|
||||||
timeout-minutes: 60
|
timeout-minutes: 60
|
||||||
steps:
|
steps:
|
||||||
- name: "Set up repository"
|
- name: "Set up repository"
|
||||||
uses: actions/checkout@v3
|
uses: actions/checkout@v2
|
||||||
with:
|
with:
|
||||||
fetch-depth: 0 # Required because of release/get_version.py
|
fetch-depth: 0 # Required because of release/get_version.py
|
||||||
- name: "Build package"
|
- name: "Build package"
|
||||||
@@ -57,11 +57,11 @@ jobs:
|
|||||||
path: build/output/debian-10/memgraph*.deb
|
path: build/output/debian-10/memgraph*.deb
|
||||||
|
|
||||||
debian-11:
|
debian-11:
|
||||||
runs-on: [self-hosted, DockerMgBuild, X64]
|
runs-on: [self-hosted, DockerMgBuild]
|
||||||
timeout-minutes: 60
|
timeout-minutes: 60
|
||||||
steps:
|
steps:
|
||||||
- name: "Set up repository"
|
- name: "Set up repository"
|
||||||
uses: actions/checkout@v3
|
uses: actions/checkout@v2
|
||||||
with:
|
with:
|
||||||
fetch-depth: 0 # Required because of release/get_version.py
|
fetch-depth: 0 # Required because of release/get_version.py
|
||||||
- name: "Build package"
|
- name: "Build package"
|
||||||
@@ -74,11 +74,11 @@ jobs:
|
|||||||
path: build/output/debian-11/memgraph*.deb
|
path: build/output/debian-11/memgraph*.deb
|
||||||
|
|
||||||
docker:
|
docker:
|
||||||
runs-on: [self-hosted, DockerMgBuild, X64]
|
runs-on: [self-hosted, DockerMgBuild]
|
||||||
timeout-minutes: 60
|
timeout-minutes: 60
|
||||||
steps:
|
steps:
|
||||||
- name: "Set up repository"
|
- name: "Set up repository"
|
||||||
uses: actions/checkout@v3
|
uses: actions/checkout@v2
|
||||||
with:
|
with:
|
||||||
fetch-depth: 0 # Required because of release/get_version.py
|
fetch-depth: 0 # Required because of release/get_version.py
|
||||||
- name: "Build package"
|
- name: "Build package"
|
||||||
@@ -93,11 +93,11 @@ jobs:
|
|||||||
path: build/output/docker/memgraph*.tar.gz
|
path: build/output/docker/memgraph*.tar.gz
|
||||||
|
|
||||||
ubuntu-1804:
|
ubuntu-1804:
|
||||||
runs-on: [self-hosted, DockerMgBuild, X64]
|
runs-on: [self-hosted, DockerMgBuild]
|
||||||
timeout-minutes: 60
|
timeout-minutes: 60
|
||||||
steps:
|
steps:
|
||||||
- name: "Set up repository"
|
- name: "Set up repository"
|
||||||
uses: actions/checkout@v3
|
uses: actions/checkout@v2
|
||||||
with:
|
with:
|
||||||
fetch-depth: 0 # Required because of release/get_version.py
|
fetch-depth: 0 # Required because of release/get_version.py
|
||||||
- name: "Build package"
|
- name: "Build package"
|
||||||
@@ -110,11 +110,11 @@ jobs:
|
|||||||
path: build/output/ubuntu-18.04/memgraph*.deb
|
path: build/output/ubuntu-18.04/memgraph*.deb
|
||||||
|
|
||||||
ubuntu-2004:
|
ubuntu-2004:
|
||||||
runs-on: [self-hosted, DockerMgBuild, X64]
|
runs-on: [self-hosted, DockerMgBuild]
|
||||||
timeout-minutes: 60
|
timeout-minutes: 60
|
||||||
steps:
|
steps:
|
||||||
- name: "Set up repository"
|
- name: "Set up repository"
|
||||||
uses: actions/checkout@v3
|
uses: actions/checkout@v2
|
||||||
with:
|
with:
|
||||||
fetch-depth: 0 # Required because of release/get_version.py
|
fetch-depth: 0 # Required because of release/get_version.py
|
||||||
- name: "Build package"
|
- name: "Build package"
|
||||||
@@ -126,29 +126,12 @@ jobs:
|
|||||||
name: ubuntu-2004
|
name: ubuntu-2004
|
||||||
path: build/output/ubuntu-20.04/memgraph*.deb
|
path: build/output/ubuntu-20.04/memgraph*.deb
|
||||||
|
|
||||||
ubuntu-2204:
|
|
||||||
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"
|
|
||||||
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:
|
debian-11-platform:
|
||||||
runs-on: [self-hosted, DockerMgBuild, X64]
|
runs-on: [self-hosted, DockerMgBuild]
|
||||||
timeout-minutes: 60
|
timeout-minutes: 60
|
||||||
steps:
|
steps:
|
||||||
- name: "Set up repository"
|
- name: "Set up repository"
|
||||||
uses: actions/checkout@v3
|
uses: actions/checkout@v2
|
||||||
with:
|
with:
|
||||||
fetch-depth: 0 # Required because of release/get_version.py
|
fetch-depth: 0 # Required because of release/get_version.py
|
||||||
- name: "Build package"
|
- name: "Build package"
|
||||||
@@ -159,20 +142,3 @@ jobs:
|
|||||||
with:
|
with:
|
||||||
name: debian-11-platform
|
name: debian-11-platform
|
||||||
path: build/output/debian-11/memgraph*.deb
|
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
49
.github/workflows/release_docker.yaml
vendored
@@ -1,49 +0,0 @@
|
|||||||
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,7 +9,6 @@
|
|||||||
*.swn
|
*.swn
|
||||||
*.swo
|
*.swo
|
||||||
*.swp
|
*.swp
|
||||||
|
|
||||||
*~
|
*~
|
||||||
.DS_Store
|
.DS_Store
|
||||||
.gdb_history
|
.gdb_history
|
||||||
@@ -27,7 +26,6 @@ src/query/frontend/opencypher/generated/
|
|||||||
tags
|
tags
|
||||||
ve/
|
ve/
|
||||||
ve3/
|
ve3/
|
||||||
.cache/
|
|
||||||
perf.data*
|
perf.data*
|
||||||
TAGS
|
TAGS
|
||||||
*.apollo_measurements
|
*.apollo_measurements
|
||||||
|
|||||||
@@ -1,24 +0,0 @@
|
|||||||
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,8 +184,7 @@ set(CMAKE_CXX_STANDARD_REQUIRED ON)
|
|||||||
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wall \
|
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wall \
|
||||||
-Werror=switch -Werror=switch-bool -Werror=return-type \
|
-Werror=switch -Werror=switch-bool -Werror=return-type \
|
||||||
-Werror=return-stack-address \
|
-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.
|
# Don't omit frame pointer in RelWithDebInfo, for additional callchain debug.
|
||||||
set(CMAKE_CXX_FLAGS_RELWITHDEBINFO
|
set(CMAKE_CXX_FLAGS_RELWITHDEBINFO
|
||||||
@@ -205,8 +204,6 @@ set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -fuse-ld=gold")
|
|||||||
# release flags
|
# release flags
|
||||||
set(CMAKE_CXX_FLAGS_RELEASE "-O2 -DNDEBUG")
|
set(CMAKE_CXX_FLAGS_RELEASE "-O2 -DNDEBUG")
|
||||||
|
|
||||||
SET(CMAKE_CXX_LINK_FLAGS "${CMAKE_CXX_LINK_FLAGS} -pthread")
|
|
||||||
|
|
||||||
#debug flags
|
#debug flags
|
||||||
set(PREFERRED_DEBUGGER "gdb" CACHE STRING
|
set(PREFERRED_DEBUGGER "gdb" CACHE STRING
|
||||||
"Tunes the debug output for your preferred debugger (gdb or lldb).")
|
"Tunes the debug output for your preferred debugger (gdb or lldb).")
|
||||||
|
|||||||
@@ -1 +1 @@
|
|||||||
* @antaljanosbenjamin @kostasrim
|
* @gitbuda @antonio2368 @antaljanosbenjamin @kostasrim @jbajic
|
||||||
|
|||||||
12
README.md
12
README.md
@@ -54,18 +54,6 @@ 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
|
to ensure that you’re getting the best possible performance consistently and
|
||||||
without surprises. It’s also ACID-compliant and highly available.
|
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
|
## :floppy_disk: Download & Install
|
||||||
|
|
||||||
### Windows
|
### Windows
|
||||||
|
|||||||
@@ -47,14 +47,6 @@ modifications:
|
|||||||
value: ""
|
value: ""
|
||||||
override: false
|
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"
|
- name: "storage_properties_on_edges"
|
||||||
value: "true"
|
value: "true"
|
||||||
override: true
|
override: true
|
||||||
|
|||||||
@@ -18,16 +18,14 @@ WIDTH = 80
|
|||||||
|
|
||||||
def wrap_text(s, initial_indent="# "):
|
def wrap_text(s, initial_indent="# "):
|
||||||
return "\n#\n".join(
|
return "\n#\n".join(
|
||||||
map(
|
map(lambda x: textwrap.fill(x, WIDTH, initial_indent=initial_indent,
|
||||||
lambda x: textwrap.fill(x, WIDTH, initial_indent=initial_indent, subsequent_indent="# "),
|
subsequent_indent="# "), s.split("\n")))
|
||||||
s.split("\n"),
|
|
||||||
)
|
|
||||||
)
|
|
||||||
|
|
||||||
|
|
||||||
def extract_flags(binary_path):
|
def extract_flags(binary_path):
|
||||||
ret = {}
|
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)
|
root = ET.fromstring(data)
|
||||||
for child in root:
|
for child in root:
|
||||||
if child.tag == "usage" and child.text.lower().count("warning"):
|
if child.tag == "usage" and child.text.lower().count("warning"):
|
||||||
@@ -48,7 +46,8 @@ def apply_config_to_flags(config, flags):
|
|||||||
for modification in config["modifications"]:
|
for modification in config["modifications"]:
|
||||||
name = modification["name"]
|
name = modification["name"]
|
||||||
if name not in flags:
|
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
|
continue
|
||||||
flags[name]["default"] = modification["value"]
|
flags[name]["default"] = modification["value"]
|
||||||
flags[name]["override"] = modification["override"]
|
flags[name]["override"] = modification["override"]
|
||||||
@@ -76,9 +75,8 @@ def extract_sections(flags):
|
|||||||
else:
|
else:
|
||||||
sections.append((current_section, current_flags))
|
sections.append((current_section, current_flags))
|
||||||
sections.append(("other", other))
|
sections.append(("other", other))
|
||||||
assert set(sum(map(lambda x: x[1], sections), [])) == set(
|
assert set(sum(map(lambda x: x[1], sections), [])) == set(flags.keys()), \
|
||||||
flags.keys()
|
"The section extraction algorithm lost some flags!"
|
||||||
), "The section extraction algorithm lost some flags!"
|
|
||||||
return sections
|
return sections
|
||||||
|
|
||||||
|
|
||||||
@@ -91,7 +89,8 @@ def generate_config_file(sections, flags):
|
|||||||
helpstr = flag["meaning"] + " [" + flag["type"] + "]"
|
helpstr = flag["meaning"] + " [" + flag["type"] + "]"
|
||||||
ret += wrap_text(helpstr) + "\n"
|
ret += wrap_text(helpstr) + "\n"
|
||||||
prefix = "# " if not flag["override"] else ""
|
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 += "\n"
|
||||||
ret += wrap_text(config["footer"])
|
ret += wrap_text(config["footer"])
|
||||||
return ret.strip() + "\n"
|
return ret.strip() + "\n"
|
||||||
@@ -99,16 +98,13 @@ def generate_config_file(sections, flags):
|
|||||||
|
|
||||||
if __name__ == "__main__":
|
if __name__ == "__main__":
|
||||||
parser = argparse.ArgumentParser()
|
parser = argparse.ArgumentParser()
|
||||||
parser.add_argument("memgraph_binary", help="path to Memgraph binary")
|
parser.add_argument("memgraph_binary",
|
||||||
parser.add_argument(
|
help="path to Memgraph binary")
|
||||||
"output_file",
|
parser.add_argument("output_file",
|
||||||
help="path where to store the generated Memgraph " "configuration file",
|
help="path where to store the generated Memgraph "
|
||||||
)
|
"configuration file")
|
||||||
parser.add_argument(
|
parser.add_argument("--config-file", default=CONFIG_FILE,
|
||||||
"--config-file",
|
help="path to generator configuration file")
|
||||||
default=CONFIG_FILE,
|
|
||||||
help="path to generator configuration file",
|
|
||||||
)
|
|
||||||
|
|
||||||
args = parser.parse_args()
|
args = parser.parse_args()
|
||||||
flags = extract_flags(args.memgraph_binary)
|
flags = extract_flags(args.memgraph_binary)
|
||||||
|
|||||||
@@ -11,7 +11,7 @@ TOOLCHAIN_BUILD_DEPS=(
|
|||||||
gnupg2 # used for archive signature verification
|
gnupg2 # used for archive signature verification
|
||||||
tar gzip bzip2 xz unzip # used for archive unpacking
|
tar gzip bzip2 xz unzip # used for archive unpacking
|
||||||
zlib-devel # zlib library used for all builds
|
zlib-devel # zlib library used for all builds
|
||||||
expat-devel libipt libipt-devel libbabeltrace-devel xz-devel python3-devel # gdb
|
expat-devel libipt-devel libbabeltrace-devel xz-devel python3-devel # gdb
|
||||||
texinfo # gdb
|
texinfo # gdb
|
||||||
libcurl-devel # cmake
|
libcurl-devel # cmake
|
||||||
curl # snappy
|
curl # snappy
|
||||||
@@ -22,7 +22,6 @@ TOOLCHAIN_BUILD_DEPS=(
|
|||||||
openssl-devel
|
openssl-devel
|
||||||
gmp-devel
|
gmp-devel
|
||||||
gperf
|
gperf
|
||||||
patch
|
|
||||||
)
|
)
|
||||||
|
|
||||||
TOOLCHAIN_RUN_DEPS=(
|
TOOLCHAIN_RUN_DEPS=(
|
||||||
@@ -106,7 +105,7 @@ install() {
|
|||||||
https://repo.ius.io/ius-release-el7.rpm
|
https://repo.ius.io/ius-release-el7.rpm
|
||||||
yum update -y
|
yum update -y
|
||||||
yum install -y wget python3 python3-pip
|
yum install -y wget python3 python3-pip
|
||||||
yum install -y git
|
yum install -y git224
|
||||||
for pkg in $1; do
|
for pkg in $1; do
|
||||||
if [ "$pkg" == libipt ]; then
|
if [ "$pkg" == libipt ]; then
|
||||||
if ! yum list installed libipt >/dev/null 2>/dev/null; then
|
if ! yum list installed libipt >/dev/null 2>/dev/null; then
|
||||||
|
|||||||
159
environment/os/centos-8.sh
Executable file
159
environment/os/centos-8.sh
Executable file
@@ -0,0 +1,159 @@
|
|||||||
|
#!/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 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
|
||||||
|
readline-devel # for cmake and llvm
|
||||||
|
libffi-devel libxml2-devel # for llvm
|
||||||
|
libedit-devel pcre-devel automake bison # for swig
|
||||||
|
file
|
||||||
|
openssl-devel
|
||||||
|
gmp-devel
|
||||||
|
gperf
|
||||||
|
)
|
||||||
|
|
||||||
|
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
|
||||||
|
readline # for cmake and llvm
|
||||||
|
libffi libxml2 # for llvm
|
||||||
|
openssl-devel
|
||||||
|
)
|
||||||
|
|
||||||
|
MEMGRAPH_BUILD_DEPS=(
|
||||||
|
git # source code control
|
||||||
|
make pkgconf-pkg-config # build system
|
||||||
|
curl wget # for downloading libs
|
||||||
|
libuuid-devel java-11-openjdk # required by antlr
|
||||||
|
readline-devel # for memgraph console
|
||||||
|
python36-devel # for query modules
|
||||||
|
openssl-devel
|
||||||
|
libseccomp-devel
|
||||||
|
python36 python3-virtualenv python3-pip nmap-ncat # for qa, macro_benchmark and stress tests
|
||||||
|
#
|
||||||
|
# IMPORTANT: python3-yaml does NOT exist on CentOS
|
||||||
|
# Install it manually using `pip3 install PyYAML`
|
||||||
|
#
|
||||||
|
PyYAML # Package name here does not correspond to the yum package!
|
||||||
|
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
|
||||||
|
sbcl # for custom Lisp C++ preprocessing
|
||||||
|
autoconf # for jemalloc code generation
|
||||||
|
libtool # for protobuf code generation
|
||||||
|
)
|
||||||
|
|
||||||
|
list() {
|
||||||
|
echo "$1"
|
||||||
|
}
|
||||||
|
|
||||||
|
check() {
|
||||||
|
local missing=""
|
||||||
|
for pkg in $1; do
|
||||||
|
if [ "$pkg" == "PyYAML" ]; then
|
||||||
|
if ! python3 -c "import yaml" >/dev/null 2>/dev/null; then
|
||||||
|
missing="$pkg $missing"
|
||||||
|
fi
|
||||||
|
continue
|
||||||
|
fi
|
||||||
|
if ! yum list installed "$pkg" >/dev/null 2>/dev/null; then
|
||||||
|
missing="$pkg $missing"
|
||||||
|
fi
|
||||||
|
done
|
||||||
|
if [ "$missing" != "" ]; then
|
||||||
|
echo "MISSING PACKAGES: $missing"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
install() {
|
||||||
|
cd "$DIR"
|
||||||
|
if [ "$EUID" -ne 0 ]; then
|
||||||
|
echo "Please run as root."
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
# 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
|
||||||
|
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
|
||||||
|
for pkg in $1; do
|
||||||
|
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
|
||||||
|
fi
|
||||||
|
continue
|
||||||
|
fi
|
||||||
|
if [ "$pkg" == libipt-devel ]; then
|
||||||
|
if ! yum 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
|
||||||
|
fi
|
||||||
|
continue
|
||||||
|
fi
|
||||||
|
if [ "$pkg" == sbcl ]; then
|
||||||
|
if ! dnf list installed cl-asdf >/dev/null 2>/dev/null; then
|
||||||
|
dnf install -y https://pkgs.dyn.su/el8/base/x86_64/cl-asdf-20101028-18.el8.noarch.rpm
|
||||||
|
fi
|
||||||
|
if ! dnf list installed common-lisp-controller >/dev/null 2>/dev/null; then
|
||||||
|
dnf install -y https://pkgs.dyn.su/el8/base/x86_64/common-lisp-controller-7.4-20.el8.noarch.rpm
|
||||||
|
fi
|
||||||
|
if ! dnf list installed sbcl >/dev/null 2>/dev/null; then
|
||||||
|
dnf install -y https://pkgs.dyn.su/el8/base/x86_64/sbcl-2.0.1-4.el8.x86_64.rpm
|
||||||
|
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
|
||||||
|
else # Running using sudo.
|
||||||
|
sudo -H -u "$SUDO_USER" bash -c "pip3 install --user PyYAML"
|
||||||
|
fi
|
||||||
|
continue
|
||||||
|
fi
|
||||||
|
dnf install -y "$pkg"
|
||||||
|
done
|
||||||
|
}
|
||||||
|
|
||||||
|
deps=$2"[*]"
|
||||||
|
"$1" "${!deps}"
|
||||||
@@ -6,12 +6,14 @@ DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" >/dev/null 2>&1 && pwd )"
|
|||||||
source "$DIR/../util.sh"
|
source "$DIR/../util.sh"
|
||||||
|
|
||||||
TOOLCHAIN_BUILD_DEPS=(
|
TOOLCHAIN_BUILD_DEPS=(
|
||||||
coreutils-common gcc gcc-c++ make # generic build tools
|
coreutils gcc gcc-c++ make # generic build tools
|
||||||
wget # used for archive download
|
wget # used for archive download
|
||||||
gnupg2 # used for archive signature verification
|
gnupg2 # used for archive signature verification
|
||||||
tar gzip bzip2 xz unzip # used for archive unpacking
|
tar gzip bzip2 xz unzip # used for archive unpacking
|
||||||
zlib-devel # zlib library used for all builds
|
zlib-devel # zlib library used for all builds
|
||||||
expat-devel xz-devel python3-devel texinfo libbabeltrace-devel # for gdb
|
expat-devel xz-devel python3-devel texinfo # for gdb
|
||||||
|
libcurl-devel # for cmake
|
||||||
|
curl # snappy
|
||||||
readline-devel # for cmake and llvm
|
readline-devel # for cmake and llvm
|
||||||
libffi-devel libxml2-devel # for llvm
|
libffi-devel libxml2-devel # for llvm
|
||||||
libedit-devel pcre-devel automake bison # for swig
|
libedit-devel pcre-devel automake bison # for swig
|
||||||
@@ -19,9 +21,6 @@ TOOLCHAIN_BUILD_DEPS=(
|
|||||||
openssl-devel
|
openssl-devel
|
||||||
gmp-devel
|
gmp-devel
|
||||||
gperf
|
gperf
|
||||||
diffutils
|
|
||||||
libipt libipt-devel # intel
|
|
||||||
patch
|
|
||||||
)
|
)
|
||||||
|
|
||||||
TOOLCHAIN_RUN_DEPS=(
|
TOOLCHAIN_RUN_DEPS=(
|
||||||
@@ -32,19 +31,18 @@ TOOLCHAIN_RUN_DEPS=(
|
|||||||
readline # for cmake and llvm
|
readline # for cmake and llvm
|
||||||
libffi libxml2 # for llvm
|
libffi libxml2 # for llvm
|
||||||
openssl-devel
|
openssl-devel
|
||||||
perl # for openssl
|
|
||||||
)
|
)
|
||||||
|
|
||||||
MEMGRAPH_BUILD_DEPS=(
|
MEMGRAPH_BUILD_DEPS=(
|
||||||
git # source code control
|
git # source code control
|
||||||
make pkgconf-pkg-config # build system
|
make pkgconf-pkg-config # build system
|
||||||
wget # for downloading libs
|
curl wget # for downloading libs
|
||||||
libuuid-devel java-11-openjdk # required by antlr
|
libuuid-devel java-11-openjdk # required by antlr
|
||||||
readline-devel # for memgraph console
|
readline-devel # for memgraph console
|
||||||
python3-devel # for query modules
|
python3-devel # for query modules
|
||||||
openssl-devel
|
openssl-devel
|
||||||
libseccomp-devel
|
libseccomp-devel
|
||||||
python3 python3-pip python3-virtualenv nmap-ncat # for qa, macro_benchmark and stress tests
|
python3 python3-virtualenv python3-pip nmap-ncat # for qa, macro_benchmark and stress tests
|
||||||
#
|
#
|
||||||
# IMPORTANT: python3-yaml does NOT exist on CentOS
|
# IMPORTANT: python3-yaml does NOT exist on CentOS
|
||||||
# Install it manually using `pip3 install PyYAML`
|
# Install it manually using `pip3 install PyYAML`
|
||||||
@@ -75,6 +73,12 @@ check() {
|
|||||||
if [ "$pkg" == "python3-virtualenv" ]; then
|
if [ "$pkg" == "python3-virtualenv" ]; then
|
||||||
continue
|
continue
|
||||||
fi
|
fi
|
||||||
|
if [ "$pkg" == sbcl ]; then
|
||||||
|
if ! sbcl --version &> /dev/null; then
|
||||||
|
missing="$pkg $missing"
|
||||||
|
fi
|
||||||
|
continue
|
||||||
|
fi
|
||||||
if ! yum list installed "$pkg" >/dev/null 2>/dev/null; then
|
if ! yum list installed "$pkg" >/dev/null 2>/dev/null; then
|
||||||
missing="$pkg $missing"
|
missing="$pkg $missing"
|
||||||
fi
|
fi
|
||||||
@@ -101,37 +105,13 @@ install() {
|
|||||||
yum update -y
|
yum update -y
|
||||||
yum install -y wget git python3 python3-pip
|
yum install -y wget git python3 python3-pip
|
||||||
for pkg in $1; do
|
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
|
|
||||||
fi
|
|
||||||
continue
|
|
||||||
fi
|
|
||||||
if [ "$pkg" == libipt-devel ]; 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
|
|
||||||
if [ "$pkg" == libbabeltrace-devel ]; then
|
|
||||||
if ! dnf list installed libbabeltrace-devel >/dev/null 2>/dev/null; then
|
|
||||||
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
|
|
||||||
if [ "$pkg" == sbcl ]; then
|
if [ "$pkg" == sbcl ]; then
|
||||||
if ! dnf list installed cl-asdf >/dev/null 2>/dev/null; then
|
if ! sbcl --version &> /dev/null; then
|
||||||
dnf install -y https://pkgs.dyn.su/el8/base/x86_64/cl-asdf-20101028-18.el8.noarch.rpm
|
curl -s https://altushost-swe.dl.sourceforge.net/project/sbcl/sbcl/1.4.2/sbcl-1.4.2-arm64-linux-binary.tar.bz2 -o /tmp/sbcl-arm64.tar.bz2
|
||||||
fi
|
tar xvjf /tmp/sbcl-arm64.tar.bz2 -C /tmp
|
||||||
if ! dnf list installed common-lisp-controller >/dev/null 2>/dev/null; then
|
pushd /tmp/sbcl-1.4.2-arm64-linux
|
||||||
dnf install -y https://pkgs.dyn.su/el8/base/x86_64/common-lisp-controller-7.4-20.el8.noarch.rpm
|
INSTALL_ROOT=/usr/local sh install.sh
|
||||||
fi
|
popd
|
||||||
if ! dnf list installed sbcl >/dev/null 2>/dev/null; then
|
|
||||||
dnf install -y https://pkgs.dyn.su/el8/base/x86_64/sbcl-2.0.1-4.el8.x86_64.rpm
|
|
||||||
fi
|
fi
|
||||||
continue
|
continue
|
||||||
fi
|
fi
|
||||||
@@ -145,11 +125,9 @@ install() {
|
|||||||
fi
|
fi
|
||||||
if [ "$pkg" == python3-virtualenv ]; then
|
if [ "$pkg" == python3-virtualenv ]; then
|
||||||
if [ -z ${SUDO_USER+x} ]; then # Running as root (e.g. Docker).
|
if [ -z ${SUDO_USER+x} ]; then # Running as root (e.g. Docker).
|
||||||
pip3 install virtualenv
|
pip3 install --user virtualenv
|
||||||
pip3 install virtualenvwrapper
|
|
||||||
else # Running using sudo.
|
else # Running using sudo.
|
||||||
sudo -H -u "$SUDO_USER" bash -c "pip3 install virtualenv"
|
sudo -H -u "$SUDO_USER" bash -c "pip3 install --user virtualenv"
|
||||||
sudo -H -u "$SUDO_USER" bash -c "pip3 install virtualenvwrapper"
|
|
||||||
fi
|
fi
|
||||||
continue
|
continue
|
||||||
fi
|
fi
|
||||||
|
|||||||
@@ -1,95 +0,0 @@
|
|||||||
#!/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
|
fi
|
||||||
apt install -y wget
|
apt install -y wget
|
||||||
for pkg in $1; do
|
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
|
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
|
wget -nv https://packages.microsoft.com/config/debian/10/packages-microsoft-prod.deb -O packages-microsoft-prod.deb
|
||||||
dpkg -i packages-microsoft-prod.deb
|
dpkg -i packages-microsoft-prod.deb
|
||||||
|
|||||||
@@ -1,93 +0,0 @@
|
|||||||
#!/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}"
|
|
||||||
2
environment/toolchain/folly.diff
Normal file
2
environment/toolchain/folly.diff
Normal file
@@ -0,0 +1,2 @@
|
|||||||
|
31d30
|
||||||
|
< add_subdirectory(logging/example)
|
||||||
@@ -1,41 +0,0 @@
|
|||||||
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
|
|
||||||
2
environment/toolchain/proxygen.diff
Normal file
2
environment/toolchain/proxygen.diff
Normal file
@@ -0,0 +1,2 @@
|
|||||||
|
24d23
|
||||||
|
< find_dependency(mvfst)
|
||||||
@@ -1,11 +0,0 @@
|
|||||||
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
|
|
||||||
16
environment/toolchain/snappy.diff
Normal file
16
environment/toolchain/snappy.diff
Normal file
@@ -0,0 +1,16 @@
|
|||||||
|
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")
|
||||||
@@ -1,29 +0,0 @@
|
|||||||
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
|
|
||||||
@@ -538,8 +538,7 @@ if [ ! -f $PREFIX/bin/clang ]; then
|
|||||||
make -j$CPUS
|
make -j$CPUS
|
||||||
if [[ "$for_arm" = false ]]; then
|
if [[ "$for_arm" = false ]]; then
|
||||||
make -j$CPUS check-clang # run clang test suite
|
make -j$CPUS check-clang # run clang test suite
|
||||||
# ldd is not used
|
make -j$CPUS check-lld # run lld test suite
|
||||||
# make -j$CPUS check-lld # run lld test suite
|
|
||||||
fi
|
fi
|
||||||
make install
|
make install
|
||||||
popd && popd
|
popd && popd
|
||||||
@@ -675,7 +674,7 @@ PROXYGEN_SHA256=5360a8ccdfb2f5a6c7b3eed331ec7ab0e2c792d579c6fff499c85c516c11fe14
|
|||||||
SNAPPY_SHA256=75c1fbb3d618dd3a0483bff0e26d0a92b495bbe5059c8b4f1c962b478b6e06e7
|
SNAPPY_SHA256=75c1fbb3d618dd3a0483bff0e26d0a92b495bbe5059c8b4f1c962b478b6e06e7
|
||||||
SNAPPY_VERSION=1.1.9
|
SNAPPY_VERSION=1.1.9
|
||||||
XZ_VERSION=5.2.5 # for LZMA
|
XZ_VERSION=5.2.5 # for LZMA
|
||||||
ZLIB_VERSION=1.2.12
|
ZLIB_VERSION=1.2.11
|
||||||
ZSTD_VERSION=1.5.0
|
ZSTD_VERSION=1.5.0
|
||||||
WANGLE_SHA256=1002e9c32b6f4837f6a760016e3b3e22f3509880ef3eaad191c80dc92655f23f
|
WANGLE_SHA256=1002e9c32b6f4837f6a760016e3b3e22f3509880ef3eaad191c80dc92655f23f
|
||||||
|
|
||||||
@@ -1030,7 +1029,7 @@ if [ ! -f $PREFIX/include/snappy.h ]; then
|
|||||||
fi
|
fi
|
||||||
tar -xzf ../archives/snappy-$SNAPPY_VERSION.tar.gz
|
tar -xzf ../archives/snappy-$SNAPPY_VERSION.tar.gz
|
||||||
pushd snappy-$SNAPPY_VERSION
|
pushd snappy-$SNAPPY_VERSION
|
||||||
patch -p1 < ../../snappy.patch
|
patch CMakeLists.txt ../../snappy.diff
|
||||||
mkdir build
|
mkdir build
|
||||||
pushd build
|
pushd build
|
||||||
cmake .. $COMMON_CMAKE_FLAGS \
|
cmake .. $COMMON_CMAKE_FLAGS \
|
||||||
@@ -1072,7 +1071,7 @@ if [ ! -d $PREFIX/include/folly ]; then
|
|||||||
mkdir folly-$FBLIBS_VERSION
|
mkdir folly-$FBLIBS_VERSION
|
||||||
tar -xzf ../archives/folly-$FBLIBS_VERSION.tar.gz -C folly-$FBLIBS_VERSION
|
tar -xzf ../archives/folly-$FBLIBS_VERSION.tar.gz -C folly-$FBLIBS_VERSION
|
||||||
pushd folly-$FBLIBS_VERSION
|
pushd folly-$FBLIBS_VERSION
|
||||||
patch -p1 < ../../folly.patch
|
patch folly/CMakeLists.txt ../../folly.diff
|
||||||
# build is used by facebook builder
|
# build is used by facebook builder
|
||||||
mkdir _build
|
mkdir _build
|
||||||
pushd _build
|
pushd _build
|
||||||
@@ -1131,7 +1130,7 @@ if [ ! -d $PREFIX/include/proxygen ]; then
|
|||||||
mkdir proxygen-$FBLIBS_VERSION
|
mkdir proxygen-$FBLIBS_VERSION
|
||||||
tar -xzf ../archives/proxygen-$FBLIBS_VERSION.tar.gz -C proxygen-$FBLIBS_VERSION
|
tar -xzf ../archives/proxygen-$FBLIBS_VERSION.tar.gz -C proxygen-$FBLIBS_VERSION
|
||||||
pushd proxygen-$FBLIBS_VERSION
|
pushd proxygen-$FBLIBS_VERSION
|
||||||
patch -p1 < ../../proxygen.patch
|
patch cmake/proxygen-config.cmake.in ../../proxygen.diff
|
||||||
# build is used by facebook builder
|
# build is used by facebook builder
|
||||||
mkdir _build
|
mkdir _build
|
||||||
pushd _build
|
pushd _build
|
||||||
@@ -1178,22 +1177,7 @@ popd
|
|||||||
|
|
||||||
# create toolchain archive
|
# create toolchain archive
|
||||||
if [ ! -f $NAME-binaries-$DISTRO.tar.gz ]; then
|
if [ ! -f $NAME-binaries-$DISTRO.tar.gz ]; then
|
||||||
DISTRO_FULL_NAME=${DISTRO}
|
tar --owner=root --group=root -cpvzf $NAME-binaries-$DISTRO.tar.gz -C /opt $NAME
|
||||||
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
|
fi
|
||||||
|
|
||||||
# output final instructions
|
# output final instructions
|
||||||
|
|||||||
@@ -5,10 +5,6 @@ operating_system() {
|
|||||||
sort | cut -d '=' -f 2- | sed 's/"//g' | paste -s -d '-'
|
sort | cut -d '=' -f 2- | sed 's/"//g' | paste -s -d '-'
|
||||||
}
|
}
|
||||||
|
|
||||||
architecture() {
|
|
||||||
uname -m
|
|
||||||
}
|
|
||||||
|
|
||||||
check_all_yum() {
|
check_all_yum() {
|
||||||
local missing=""
|
local missing=""
|
||||||
for pkg in $1; do
|
for pkg in $1; do
|
||||||
|
|||||||
File diff suppressed because it is too large
Load Diff
314
include/mgp.py
314
include/mgp.py
@@ -40,7 +40,6 @@ class InvalidContextError(Exception):
|
|||||||
"""
|
"""
|
||||||
Signals using a graph element instance outside of the registered procedure.
|
Signals using a graph element instance outside of the registered procedure.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
pass
|
pass
|
||||||
|
|
||||||
|
|
||||||
@@ -48,7 +47,6 @@ class UnknownError(_mgp.UnknownError):
|
|||||||
"""
|
"""
|
||||||
Signals unspecified failure.
|
Signals unspecified failure.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
pass
|
pass
|
||||||
|
|
||||||
|
|
||||||
@@ -56,7 +54,6 @@ class UnableToAllocateError(_mgp.UnableToAllocateError):
|
|||||||
"""
|
"""
|
||||||
Signals failed memory allocation.
|
Signals failed memory allocation.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
pass
|
pass
|
||||||
|
|
||||||
|
|
||||||
@@ -64,7 +61,6 @@ class InsufficientBufferError(_mgp.InsufficientBufferError):
|
|||||||
"""
|
"""
|
||||||
Signals that some buffer is not big enough.
|
Signals that some buffer is not big enough.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
pass
|
pass
|
||||||
|
|
||||||
|
|
||||||
@@ -73,7 +69,6 @@ class OutOfRangeError(_mgp.OutOfRangeError):
|
|||||||
Signals that an index-like parameter has a value that is outside its
|
Signals that an index-like parameter has a value that is outside its
|
||||||
possible values.
|
possible values.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
pass
|
pass
|
||||||
|
|
||||||
|
|
||||||
@@ -82,7 +77,6 @@ class LogicErrorError(_mgp.LogicErrorError):
|
|||||||
Signals faulty logic within the program such as violating logical
|
Signals faulty logic within the program such as violating logical
|
||||||
preconditions or class invariants and may be preventable.
|
preconditions or class invariants and may be preventable.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
pass
|
pass
|
||||||
|
|
||||||
|
|
||||||
@@ -90,7 +84,6 @@ class DeletedObjectError(_mgp.DeletedObjectError):
|
|||||||
"""
|
"""
|
||||||
Signals accessing an already deleted object.
|
Signals accessing an already deleted object.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
pass
|
pass
|
||||||
|
|
||||||
|
|
||||||
@@ -98,7 +91,6 @@ class InvalidArgumentError(_mgp.InvalidArgumentError):
|
|||||||
"""
|
"""
|
||||||
Signals that some of the arguments have invalid values.
|
Signals that some of the arguments have invalid values.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
pass
|
pass
|
||||||
|
|
||||||
|
|
||||||
@@ -106,7 +98,6 @@ class KeyAlreadyExistsError(_mgp.KeyAlreadyExistsError):
|
|||||||
"""
|
"""
|
||||||
Signals that a key already exists in a container-like object.
|
Signals that a key already exists in a container-like object.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
pass
|
pass
|
||||||
|
|
||||||
|
|
||||||
@@ -114,7 +105,6 @@ class ImmutableObjectError(_mgp.ImmutableObjectError):
|
|||||||
"""
|
"""
|
||||||
Signals modification of an immutable object.
|
Signals modification of an immutable object.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
pass
|
pass
|
||||||
|
|
||||||
|
|
||||||
@@ -122,7 +112,6 @@ class ValueConversionError(_mgp.ValueConversionError):
|
|||||||
"""
|
"""
|
||||||
Signals that the conversion failed between python and cypher values.
|
Signals that the conversion failed between python and cypher values.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
pass
|
pass
|
||||||
|
|
||||||
|
|
||||||
@@ -131,14 +120,12 @@ class SerializationError(_mgp.SerializationError):
|
|||||||
Signals serialization error caused by concurrent modifications from
|
Signals serialization error caused by concurrent modifications from
|
||||||
different transactions.
|
different transactions.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
pass
|
pass
|
||||||
|
|
||||||
|
|
||||||
class Label:
|
class Label:
|
||||||
"""Label of a Vertex."""
|
"""Label of a Vertex."""
|
||||||
|
__slots__ = ('_name',)
|
||||||
__slots__ = ("_name",)
|
|
||||||
|
|
||||||
def __init__(self, name: str):
|
def __init__(self, name: str):
|
||||||
self._name = name
|
self._name = name
|
||||||
@@ -158,22 +145,19 @@ class Label:
|
|||||||
# Named property value of a Vertex or an Edge.
|
# Named property value of a Vertex or an Edge.
|
||||||
# It would be better to use typing.NamedTuple with typed fields, but that is
|
# It would be better to use typing.NamedTuple with typed fields, but that is
|
||||||
# not available in Python 3.5.
|
# not available in Python 3.5.
|
||||||
Property = namedtuple("Property", ("name", "value"))
|
Property = namedtuple('Property', ('name', 'value'))
|
||||||
|
|
||||||
|
|
||||||
class Properties:
|
class Properties:
|
||||||
"""
|
"""
|
||||||
A collection of properties either on a Vertex or an Edge.
|
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):
|
def __init__(self, vertex_or_edge):
|
||||||
if not isinstance(vertex_or_edge, (_mgp.Vertex, _mgp.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._len = None
|
||||||
self._vertex_or_edge = vertex_or_edge
|
self._vertex_or_edge = vertex_or_edge
|
||||||
|
|
||||||
@@ -346,8 +330,7 @@ class Properties:
|
|||||||
|
|
||||||
class EdgeType:
|
class EdgeType:
|
||||||
"""Type of an Edge."""
|
"""Type of an Edge."""
|
||||||
|
__slots__ = ('_name',)
|
||||||
__slots__ = ("_name",)
|
|
||||||
|
|
||||||
def __init__(self, name):
|
def __init__(self, name):
|
||||||
self._name = name
|
self._name = name
|
||||||
@@ -365,7 +348,7 @@ class EdgeType:
|
|||||||
|
|
||||||
|
|
||||||
if sys.version_info >= (3, 5, 2):
|
if sys.version_info >= (3, 5, 2):
|
||||||
EdgeId = typing.NewType("EdgeId", int)
|
EdgeId = typing.NewType('EdgeId', int)
|
||||||
else:
|
else:
|
||||||
EdgeId = int
|
EdgeId = int
|
||||||
|
|
||||||
@@ -377,12 +360,12 @@ class Edge:
|
|||||||
a query. You should not globally store an instance of an Edge. Using an
|
a query. You should not globally store an instance of an Edge. Using an
|
||||||
invalid Edge instance will raise InvalidContextError.
|
invalid Edge instance will raise InvalidContextError.
|
||||||
"""
|
"""
|
||||||
|
__slots__ = ('_edge',)
|
||||||
__slots__ = ("_edge",)
|
|
||||||
|
|
||||||
def __init__(self, edge):
|
def __init__(self, edge):
|
||||||
if not isinstance(edge, _mgp.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
|
self._edge = edge
|
||||||
|
|
||||||
def __deepcopy__(self, memo):
|
def __deepcopy__(self, memo):
|
||||||
@@ -425,7 +408,7 @@ class Edge:
|
|||||||
return EdgeType(self._edge.get_type_name())
|
return EdgeType(self._edge.get_type_name())
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def from_vertex(self) -> "Vertex":
|
def from_vertex(self) -> 'Vertex':
|
||||||
"""
|
"""
|
||||||
Get the source vertex.
|
Get the source vertex.
|
||||||
|
|
||||||
@@ -436,7 +419,7 @@ class Edge:
|
|||||||
return Vertex(self._edge.from_vertex())
|
return Vertex(self._edge.from_vertex())
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def to_vertex(self) -> "Vertex":
|
def to_vertex(self) -> 'Vertex':
|
||||||
"""
|
"""
|
||||||
Get the destination vertex.
|
Get the destination vertex.
|
||||||
|
|
||||||
@@ -470,7 +453,7 @@ class Edge:
|
|||||||
|
|
||||||
|
|
||||||
if sys.version_info >= (3, 5, 2):
|
if sys.version_info >= (3, 5, 2):
|
||||||
VertexId = typing.NewType("VertexId", int)
|
VertexId = typing.NewType('VertexId', int)
|
||||||
else:
|
else:
|
||||||
VertexId = int
|
VertexId = int
|
||||||
|
|
||||||
@@ -482,12 +465,12 @@ class Vertex:
|
|||||||
in a query. You should not globally store an instance of a Vertex. Using an
|
in a query. You should not globally store an instance of a Vertex. Using an
|
||||||
invalid Vertex instance will raise InvalidContextError.
|
invalid Vertex instance will raise InvalidContextError.
|
||||||
"""
|
"""
|
||||||
|
__slots__ = ('_vertex',)
|
||||||
__slots__ = ("_vertex",)
|
|
||||||
|
|
||||||
def __init__(self, vertex):
|
def __init__(self, vertex):
|
||||||
if not isinstance(vertex, _mgp.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
|
self._vertex = vertex
|
||||||
|
|
||||||
def __deepcopy__(self, memo):
|
def __deepcopy__(self, memo):
|
||||||
@@ -530,7 +513,8 @@ class Vertex:
|
|||||||
"""
|
"""
|
||||||
if not self.is_valid():
|
if not self.is_valid():
|
||||||
raise InvalidContextError()
|
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:
|
def add_label(self, label: str) -> None:
|
||||||
"""
|
"""
|
||||||
@@ -631,8 +615,7 @@ class Vertex:
|
|||||||
|
|
||||||
class Path:
|
class Path:
|
||||||
"""Path containing Vertex and Edge instances."""
|
"""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]):
|
def __init__(self, starting_vertex_or_path: typing.Union[_mgp.Path, Vertex]):
|
||||||
"""Initialize with a starting Vertex.
|
"""Initialize with a starting Vertex.
|
||||||
@@ -653,7 +636,8 @@ class Path:
|
|||||||
raise InvalidContextError()
|
raise InvalidContextError()
|
||||||
self._path = _mgp.Path.make_with_start(vertex)
|
self._path = _mgp.Path.make_with_start(vertex)
|
||||||
else:
|
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):
|
def __copy__(self):
|
||||||
if not self.is_valid():
|
if not self.is_valid():
|
||||||
@@ -694,7 +678,8 @@ class Path:
|
|||||||
extension.
|
extension.
|
||||||
"""
|
"""
|
||||||
if not isinstance(edge, Edge):
|
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():
|
if not self.is_valid() or not edge.is_valid():
|
||||||
raise InvalidContextError()
|
raise InvalidContextError()
|
||||||
self._path.expand(edge._edge)
|
self._path.expand(edge._edge)
|
||||||
@@ -713,7 +698,8 @@ class Path:
|
|||||||
raise InvalidContextError()
|
raise InvalidContextError()
|
||||||
if self._vertices is None:
|
if self._vertices is None:
|
||||||
num_vertices = self._path.size() + 1
|
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
|
return self._vertices
|
||||||
|
|
||||||
@property
|
@property
|
||||||
@@ -727,14 +713,14 @@ class Path:
|
|||||||
raise InvalidContextError()
|
raise InvalidContextError()
|
||||||
if self._edges is None:
|
if self._edges is None:
|
||||||
num_edges = self._path.size()
|
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
|
return self._edges
|
||||||
|
|
||||||
|
|
||||||
class Record:
|
class Record:
|
||||||
"""Represents a record of resulting field values."""
|
"""Represents a record of resulting field values."""
|
||||||
|
__slots__ = ('fields',)
|
||||||
__slots__ = ("fields",)
|
|
||||||
|
|
||||||
def __init__(self, **kwargs):
|
def __init__(self, **kwargs):
|
||||||
"""Initialize with name=value fields in kwargs."""
|
"""Initialize with name=value fields in kwargs."""
|
||||||
@@ -743,12 +729,12 @@ class Record:
|
|||||||
|
|
||||||
class Vertices:
|
class Vertices:
|
||||||
"""Iterable over vertices in a graph."""
|
"""Iterable over vertices in a graph."""
|
||||||
|
__slots__ = ('_graph', '_len')
|
||||||
__slots__ = ("_graph", "_len")
|
|
||||||
|
|
||||||
def __init__(self, graph):
|
def __init__(self, graph):
|
||||||
if not isinstance(graph, _mgp.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._graph = graph
|
||||||
self._len = None
|
self._len = None
|
||||||
|
|
||||||
@@ -805,12 +791,12 @@ class Vertices:
|
|||||||
|
|
||||||
class Graph:
|
class Graph:
|
||||||
"""State of the graph database in current ProcCtx."""
|
"""State of the graph database in current ProcCtx."""
|
||||||
|
__slots__ = ('_graph',)
|
||||||
__slots__ = ("_graph",)
|
|
||||||
|
|
||||||
def __init__(self, graph):
|
def __init__(self, graph):
|
||||||
if not isinstance(graph, _mgp.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._graph = graph
|
||||||
|
|
||||||
def __deepcopy__(self, memo):
|
def __deepcopy__(self, memo):
|
||||||
@@ -899,7 +885,8 @@ class Graph:
|
|||||||
raise InvalidContextError()
|
raise InvalidContextError()
|
||||||
self._graph.detach_delete_vertex(vertex._vertex)
|
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.
|
Create an edge.
|
||||||
|
|
||||||
@@ -912,7 +899,8 @@ class Graph:
|
|||||||
"""
|
"""
|
||||||
if not self.is_valid():
|
if not self.is_valid():
|
||||||
raise InvalidContextError()
|
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:
|
def delete_edge(self, edge: Edge) -> None:
|
||||||
"""
|
"""
|
||||||
@@ -930,7 +918,6 @@ class Graph:
|
|||||||
|
|
||||||
class AbortError(Exception):
|
class AbortError(Exception):
|
||||||
"""Signals that the procedure was asked to abort its execution."""
|
"""Signals that the procedure was asked to abort its execution."""
|
||||||
|
|
||||||
pass
|
pass
|
||||||
|
|
||||||
|
|
||||||
@@ -940,12 +927,12 @@ class ProcCtx:
|
|||||||
Access to a ProcCtx is only valid during a single execution of a procedure
|
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.
|
in a query. You should not globally store a ProcCtx instance.
|
||||||
"""
|
"""
|
||||||
|
__slots__ = ('_graph',)
|
||||||
__slots__ = ("_graph",)
|
|
||||||
|
|
||||||
def __init__(self, graph):
|
def __init__(self, graph):
|
||||||
if not isinstance(graph, _mgp.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)
|
self._graph = Graph(graph)
|
||||||
|
|
||||||
def is_valid(self) -> bool:
|
def is_valid(self) -> bool:
|
||||||
@@ -982,7 +969,8 @@ LocalDateTime = datetime.datetime
|
|||||||
|
|
||||||
Duration = datetime.timedelta
|
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
|
List = typing.List
|
||||||
|
|
||||||
@@ -1015,7 +1003,7 @@ def _typing_to_cypher_type(type_):
|
|||||||
Date: _mgp.type_date(),
|
Date: _mgp.type_date(),
|
||||||
LocalTime: _mgp.type_local_time(),
|
LocalTime: _mgp.type_local_time(),
|
||||||
LocalDateTime: _mgp.type_local_date_time(),
|
LocalDateTime: _mgp.type_local_date_time(),
|
||||||
Duration: _mgp.type_duration(),
|
Duration: _mgp.type_duration()
|
||||||
}
|
}
|
||||||
try:
|
try:
|
||||||
return simple_types[type_]
|
return simple_types[type_]
|
||||||
@@ -1033,14 +1021,14 @@ def _typing_to_cypher_type(type_):
|
|||||||
if type(None) in type_args:
|
if type(None) in type_args:
|
||||||
types = tuple(t for t in type_args if t is not type(None)) # noqa E721
|
types = tuple(t for t in type_args if t is not type(None)) # noqa E721
|
||||||
if len(types) == 1:
|
if len(types) == 1:
|
||||||
(type_arg,) = types
|
type_arg, = types
|
||||||
else:
|
else:
|
||||||
# We cannot do typing.Union[*types], so do the equivalent
|
# We cannot do typing.Union[*types], so do the equivalent
|
||||||
# with __getitem__ which does not even need arg unpacking.
|
# with __getitem__ which does not even need arg unpacking.
|
||||||
type_arg = typing.Union.__getitem__(types)
|
type_arg = typing.Union.__getitem__(types)
|
||||||
return _mgp.type_nullable(_typing_to_cypher_type(type_arg))
|
return _mgp.type_nullable(_typing_to_cypher_type(type_arg))
|
||||||
elif complex_type == list:
|
elif complex_type == list:
|
||||||
(type_arg,) = type_args
|
type_arg, = type_args
|
||||||
return _mgp.type_list(_typing_to_cypher_type(type_arg))
|
return _mgp.type_list(_typing_to_cypher_type(type_arg))
|
||||||
raise UnsupportedTypingError(type_)
|
raise UnsupportedTypingError(type_)
|
||||||
else:
|
else:
|
||||||
@@ -1050,17 +1038,13 @@ def _typing_to_cypher_type(type_):
|
|||||||
# printed the same way. `typing.List[type]` is printed as such, while
|
# printed the same way. `typing.List[type]` is printed as such, while
|
||||||
# `typing.Optional[type]` is printed as 'typing.Union[type, NoneType]'
|
# `typing.Optional[type]` is printed as 'typing.Union[type, NoneType]'
|
||||||
def parse_type_args(type_as_str):
|
def parse_type_args(type_as_str):
|
||||||
return tuple(
|
return tuple(map(str.strip,
|
||||||
map(
|
type_as_str[type_as_str.index('[') + 1: -1].split(',')))
|
||||||
str.strip,
|
|
||||||
type_as_str[type_as_str.index("[") + 1 : -1].split(","),
|
|
||||||
)
|
|
||||||
)
|
|
||||||
|
|
||||||
def fully_qualified_name(cls):
|
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.__name__
|
||||||
return cls.__module__ + "." + cls.__name__
|
return cls.__module__ + '.' + cls.__name__
|
||||||
|
|
||||||
def get_simple_type(type_as_str):
|
def get_simple_type(type_as_str):
|
||||||
for simple_type, cypher_type in simple_types.items():
|
for simple_type, cypher_type in simple_types.items():
|
||||||
@@ -1076,26 +1060,28 @@ def _typing_to_cypher_type(type_):
|
|||||||
pass
|
pass
|
||||||
|
|
||||||
def parse_typing(type_as_str):
|
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)
|
type_args_as_str = parse_type_args(type_as_str)
|
||||||
none_type_as_str = type(None).__name__
|
none_type_as_str = type(None).__name__
|
||||||
if none_type_as_str in type_args_as_str:
|
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:
|
if len(types) == 1:
|
||||||
(type_arg_as_str,) = types
|
type_arg_as_str, = types
|
||||||
else:
|
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)
|
simple_type = get_simple_type(type_arg_as_str)
|
||||||
if simple_type is not None:
|
if simple_type is not None:
|
||||||
return _mgp.type_nullable(simple_type)
|
return _mgp.type_nullable(simple_type)
|
||||||
return _mgp.type_nullable(parse_typing(type_arg_as_str))
|
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)
|
type_arg_as_str = parse_type_args(type_as_str)
|
||||||
|
|
||||||
if len(type_arg_as_str) > 1:
|
if len(type_arg_as_str) > 1:
|
||||||
# Nested object could be a type consisting of a list of types (e.g. mgp.Map)
|
# Nested object could be a type consisting of a list of types (e.g. mgp.Map)
|
||||||
# so we need to join the parts.
|
# 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:
|
else:
|
||||||
type_arg_as_str = type_arg_as_str[0]
|
type_arg_as_str = type_arg_as_str[0]
|
||||||
|
|
||||||
@@ -1110,11 +1096,9 @@ def _typing_to_cypher_type(type_):
|
|||||||
|
|
||||||
# Procedure registration
|
# Procedure registration
|
||||||
|
|
||||||
|
|
||||||
class Deprecated:
|
class Deprecated:
|
||||||
"""Annotate a resulting Record's field as deprecated."""
|
"""Annotate a resulting Record's field as deprecated."""
|
||||||
|
__slots__ = ('field_type',)
|
||||||
__slots__ = ("field_type",)
|
|
||||||
|
|
||||||
def __init__(self, type_):
|
def __init__(self, type_):
|
||||||
self.field_type = type_
|
self.field_type = type_
|
||||||
@@ -1122,7 +1106,8 @@ class Deprecated:
|
|||||||
|
|
||||||
def raise_if_does_not_meet_requirements(func: typing.Callable[..., Record]):
|
def raise_if_does_not_meet_requirements(func: typing.Callable[..., Record]):
|
||||||
if not callable(func):
|
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):
|
if inspect.iscoroutinefunction(func):
|
||||||
raise TypeError("Callable must not be 'async def' function")
|
raise TypeError("Callable must not be 'async def' function")
|
||||||
if sys.version_info >= (3, 6):
|
if sys.version_info >= (3, 6):
|
||||||
@@ -1132,25 +1117,24 @@ def raise_if_does_not_meet_requirements(func: typing.Callable[..., Record]):
|
|||||||
raise NotImplementedError("Generator functions are not supported")
|
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)
|
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)
|
sig = inspect.signature(func)
|
||||||
params = tuple(sig.parameters.values())
|
params = tuple(sig.parameters.values())
|
||||||
if params and params[0].annotation is ProcCtx:
|
if params and params[0].annotation is ProcCtx:
|
||||||
|
|
||||||
@wraps(func)
|
@wraps(func)
|
||||||
def wrapper(graph, args):
|
def wrapper(graph, args):
|
||||||
return func(ProcCtx(graph), *args)
|
return func(ProcCtx(graph), *args)
|
||||||
|
|
||||||
params = params[1:]
|
params = params[1:]
|
||||||
mgp_proc = register_func(_mgp._MODULE, wrapper)
|
mgp_proc = register_func(_mgp._MODULE, wrapper)
|
||||||
else:
|
else:
|
||||||
|
|
||||||
@wraps(func)
|
@wraps(func)
|
||||||
def wrapper(graph, args):
|
def wrapper(graph, args):
|
||||||
return func(*args)
|
return func(*args)
|
||||||
|
|
||||||
mgp_proc = register_func(_mgp._MODULE, wrapper)
|
mgp_proc = register_func(_mgp._MODULE, wrapper)
|
||||||
for param in params:
|
for param in params:
|
||||||
name = param.name
|
name = param.name
|
||||||
@@ -1165,7 +1149,8 @@ def _register_proc(func: typing.Callable[..., Record], is_write: bool):
|
|||||||
if sig.return_annotation is not sig.empty:
|
if sig.return_annotation is not sig.empty:
|
||||||
record = sig.return_annotation
|
record = sig.return_annotation
|
||||||
if not isinstance(record, Record):
|
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():
|
for name, type_ in record.fields.items():
|
||||||
if isinstance(type_, Deprecated):
|
if isinstance(type_, Deprecated):
|
||||||
cypher_type = _typing_to_cypher_type(type_.field_type)
|
cypher_type = _typing_to_cypher_type(type_.field_type)
|
||||||
@@ -1179,15 +1164,16 @@ def read_proc(func: typing.Callable[..., Record]):
|
|||||||
"""
|
"""
|
||||||
Register `func` as a read-only procedure of the current module.
|
Register `func` as a read-only procedure of the current module.
|
||||||
|
|
||||||
The decorator `read_proc` is meant to be used to register module procedures.
|
`read_proc` is meant to be used as a decorator function to register module
|
||||||
The registered `func` needs to be a callable which optionally takes
|
procedures. The registered `func` needs to be a callable which optionally
|
||||||
`ProcCtx` as its first argument. Other arguments of `func` will be bound to
|
takes `ProcCtx` as the first argument. Other arguments of `func` will be
|
||||||
values passed in the cypherQuery. The full signature of `func` needs to be
|
bound to values passed in the cypherQuery. The full signature of `func`
|
||||||
annotated with types. The return type must be `Record(field_name=type, ...)`
|
needs to be annotated with types. The return type must be
|
||||||
and the procedure must produce either a complete Record or None. To mark a
|
`Record(field_name=type, ...)` and the procedure must produce either a
|
||||||
field as deprecated, use `Record(field_name=Deprecated(type), ...)`.
|
complete Record or None. To mark a field as deprecated, use
|
||||||
Multiple records can be produced by returning an iterable of them.
|
`Record(field_name=Deprecated(type), ...)`. Multiple records can be
|
||||||
Registering generator functions is currently not supported.
|
produced by returning an iterable of them. Registering generator functions
|
||||||
|
is currently not supported.
|
||||||
|
|
||||||
Example usage.
|
Example usage.
|
||||||
|
|
||||||
@@ -1221,16 +1207,16 @@ def write_proc(func: typing.Callable[..., Record]):
|
|||||||
"""
|
"""
|
||||||
Register `func` as a writeable procedure of the current module.
|
Register `func` as a writeable procedure of the current module.
|
||||||
|
|
||||||
The decorator `write_proc` is meant to be used to register module
|
`write_proc` is meant to be used as a decorator function to register module
|
||||||
procedures. The registered `func` needs to be a callable which optionally
|
procedures. The registered `func` needs to be a callable which optionally
|
||||||
takes `ProcCtx` as the first argument. Other arguments of `func` will be
|
takes `ProcCtx` as the first argument. Other arguments of `func` will be
|
||||||
bound to values passed in the cypherQuery. The full signature of `func`
|
bound to values passed in the cypherQuery. The full signature of `func`
|
||||||
needs to be annotated with types. The return type must be
|
needs to be annotated with types. The return type must be
|
||||||
`Record(field_name=type, ...)` and the procedure must produce either a
|
`Record(field_name=type, ...)` and the procedure must produce either a
|
||||||
complete Record or None. To mark a field as deprecated, use
|
complete Record or None. To mark a field as deprecated, use
|
||||||
`Record(field_name=Deprecated(type), ...)`. Multiple records can be produced
|
`Record(field_name=Deprecated(type), ...)`. Multiple records can be
|
||||||
by returning an iterable of them. Registering generator functions is
|
produced by returning an iterable of them. Registering generator functions
|
||||||
currently not supported.
|
is currently not supported.
|
||||||
|
|
||||||
Example usage.
|
Example usage.
|
||||||
|
|
||||||
@@ -1271,22 +1257,20 @@ class InvalidMessageError(Exception):
|
|||||||
"""
|
"""
|
||||||
Signals using a message instance outside of the registered transformation.
|
Signals using a message instance outside of the registered transformation.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
pass
|
pass
|
||||||
|
|
||||||
|
|
||||||
SOURCE_TYPE_KAFKA = _mgp.SOURCE_TYPE_KAFKA
|
SOURCE_TYPE_KAFKA = _mgp.SOURCE_TYPE_KAFKA
|
||||||
SOURCE_TYPE_PULSAR = _mgp.SOURCE_TYPE_PULSAR
|
SOURCE_TYPE_PULSAR = _mgp.SOURCE_TYPE_PULSAR
|
||||||
|
|
||||||
|
|
||||||
class Message:
|
class Message:
|
||||||
"""Represents a message from a stream."""
|
"""Represents a message from a stream."""
|
||||||
|
__slots__ = ('_message',)
|
||||||
__slots__ = ("_message",)
|
|
||||||
|
|
||||||
def __init__(self, message):
|
def __init__(self, message):
|
||||||
if not isinstance(message, _mgp.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
|
self._message = message
|
||||||
|
|
||||||
def __deepcopy__(self, memo):
|
def __deepcopy__(self, memo):
|
||||||
@@ -1369,18 +1353,17 @@ class Message:
|
|||||||
|
|
||||||
class InvalidMessagesError(Exception):
|
class InvalidMessagesError(Exception):
|
||||||
"""Signals using a messages instance outside of the registered transformation."""
|
"""Signals using a messages instance outside of the registered transformation."""
|
||||||
|
|
||||||
pass
|
pass
|
||||||
|
|
||||||
|
|
||||||
class Messages:
|
class Messages:
|
||||||
"""Represents a list of messages from a stream."""
|
"""Represents a list of messages from a stream."""
|
||||||
|
__slots__ = ('_messages',)
|
||||||
__slots__ = ("_messages",)
|
|
||||||
|
|
||||||
def __init__(self, messages):
|
def __init__(self, messages):
|
||||||
if not isinstance(messages, _mgp.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
|
self._messages = messages
|
||||||
|
|
||||||
def __deepcopy__(self, memo):
|
def __deepcopy__(self, memo):
|
||||||
@@ -1412,12 +1395,12 @@ class TransCtx:
|
|||||||
Access to a TransCtx is only valid during a single execution of a transformation.
|
Access to a TransCtx is only valid during a single execution of a transformation.
|
||||||
You should not globally store a TransCtx instance.
|
You should not globally store a TransCtx instance.
|
||||||
"""
|
"""
|
||||||
|
__slots__ = ('_graph')
|
||||||
__slots__ = "_graph"
|
|
||||||
|
|
||||||
def __init__(self, graph):
|
def __init__(self, graph):
|
||||||
if not isinstance(graph, _mgp.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)
|
self._graph = Graph(graph)
|
||||||
|
|
||||||
def is_valid(self) -> bool:
|
def is_valid(self) -> bool:
|
||||||
@@ -1437,116 +1420,21 @@ def transformation(func: typing.Callable[..., Record]):
|
|||||||
params = tuple(sig.parameters.values())
|
params = tuple(sig.parameters.values())
|
||||||
if not params or not params[0].annotation is Messages:
|
if not params or not params[0].annotation is Messages:
|
||||||
if not len(params) == 2 or not params[1].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:
|
if params[0].annotation is TransCtx:
|
||||||
|
|
||||||
@wraps(func)
|
@wraps(func)
|
||||||
def wrapper(graph, messages):
|
def wrapper(graph, messages):
|
||||||
return func(TransCtx(graph), messages)
|
return func(TransCtx(graph), messages)
|
||||||
|
|
||||||
_mgp._MODULE.add_transformation(wrapper)
|
_mgp._MODULE.add_transformation(wrapper)
|
||||||
else:
|
else:
|
||||||
|
|
||||||
@wraps(func)
|
@wraps(func)
|
||||||
def wrapper(graph, messages):
|
def wrapper(graph, messages):
|
||||||
return func(messages)
|
return func(messages)
|
||||||
|
|
||||||
_mgp._MODULE.add_transformation(wrapper)
|
_mgp._MODULE.add_transformation(wrapper)
|
||||||
return func
|
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_exceptions():
|
||||||
def wrap_function(func):
|
def wrap_function(func):
|
||||||
@wraps(func)
|
@wraps(func)
|
||||||
@@ -1575,7 +1463,6 @@ def _wrap_exceptions():
|
|||||||
raise ValueConversionError(e)
|
raise ValueConversionError(e)
|
||||||
except _mgp.SerializationError as e:
|
except _mgp.SerializationError as e:
|
||||||
raise SerializationError(e)
|
raise SerializationError(e)
|
||||||
|
|
||||||
return wrapped_func
|
return wrapped_func
|
||||||
|
|
||||||
def wrap_prop_func(func):
|
def wrap_prop_func(func):
|
||||||
@@ -1586,16 +1473,11 @@ def _wrap_exceptions():
|
|||||||
if inspect.isfunction(obj):
|
if inspect.isfunction(obj):
|
||||||
setattr(cls, name, wrap_function(obj))
|
setattr(cls, name, wrap_function(obj))
|
||||||
elif isinstance(obj, property):
|
elif isinstance(obj, property):
|
||||||
setattr(
|
setattr(cls, name, property(
|
||||||
cls,
|
wrap_prop_func(obj.fget),
|
||||||
name,
|
wrap_prop_func(obj.fset),
|
||||||
property(
|
wrap_prop_func(obj.fdel),
|
||||||
wrap_prop_func(obj.fget),
|
obj.__doc__))
|
||||||
wrap_prop_func(obj.fset),
|
|
||||||
wrap_prop_func(obj.fdel),
|
|
||||||
obj.__doc__,
|
|
||||||
),
|
|
||||||
)
|
|
||||||
|
|
||||||
def defined_in_this_module(obj: object):
|
def defined_in_this_module(obj: object):
|
||||||
return getattr(obj, "__module__", "") == __name__
|
return getattr(obj, "__module__", "") == __name__
|
||||||
|
|||||||
16
init
16
init
@@ -24,7 +24,7 @@ function setup_virtualenv () {
|
|||||||
fi
|
fi
|
||||||
|
|
||||||
# create new virtualenv
|
# create new virtualenv
|
||||||
python3 -m virtualenv -p python3 ve3 || exit 1
|
virtualenv -p python3 ve3 || exit 1
|
||||||
source ve3/bin/activate
|
source ve3/bin/activate
|
||||||
pip --timeout 1000 install -r requirements.txt || exit 1
|
pip --timeout 1000 install -r requirements.txt || exit 1
|
||||||
deactivate
|
deactivate
|
||||||
@@ -65,14 +65,8 @@ else
|
|||||||
fi
|
fi
|
||||||
|
|
||||||
DISTRO=$(operating_system)
|
DISTRO=$(operating_system)
|
||||||
ARCHITECTURE=$(architecture)
|
echo "ALL BUILD PACKAGES: $($DIR/environment/os/$DISTRO.sh list MEMGRAPH_BUILD_DEPS)"
|
||||||
if [ "${ARCHITECTURE}" = "arm64" ] || [ "${ARCHITECTURE}" = "aarch64" ]; then
|
$DIR/environment/os/$DISTRO.sh check MEMGRAPH_BUILD_DEPS
|
||||||
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..."
|
echo "All packages are in-place..."
|
||||||
|
|
||||||
# create a default build directory
|
# create a default build directory
|
||||||
@@ -135,7 +129,3 @@ for hook in $(find $DIR/.githooks -type f -printf "%f\n"); do
|
|||||||
ln -s -f "$DIR/.githooks/$hook" "$DIR/.git/hooks/$hook"
|
ln -s -f "$DIR/.githooks/$hook" "$DIR/.git/hooks/$hook"
|
||||||
echo "Added $hook hook"
|
echo "Added $hook hook"
|
||||||
done;
|
done;
|
||||||
|
|
||||||
# Install precommit hook
|
|
||||||
python3 -m pip install pre-commit
|
|
||||||
python3 -m pre_commit install
|
|
||||||
|
|||||||
1
libs/.gitignore
vendored
1
libs/.gitignore
vendored
@@ -4,4 +4,5 @@
|
|||||||
!cleanup.sh
|
!cleanup.sh
|
||||||
!CMakeLists.txt
|
!CMakeLists.txt
|
||||||
!__main.cpp
|
!__main.cpp
|
||||||
|
!jemalloc.cmake
|
||||||
!pulsar.patch
|
!pulsar.patch
|
||||||
|
|||||||
55
libs/jemalloc.cmake
Normal file
55
libs/jemalloc.cmake
Normal file
@@ -0,0 +1,55 @@
|
|||||||
|
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)
|
||||||
@@ -107,19 +107,25 @@ declare -A primary_urls=(
|
|||||||
["antlr4-code"]="http://$local_cache_host/git/antlr4.git"
|
["antlr4-code"]="http://$local_cache_host/git/antlr4.git"
|
||||||
["antlr4-generator"]="http://$local_cache_host/file/antlr-4.9.2-complete.jar"
|
["antlr4-generator"]="http://$local_cache_host/file/antlr-4.9.2-complete.jar"
|
||||||
["cppitertools"]="http://$local_cache_host/git/cppitertools.git"
|
["cppitertools"]="http://$local_cache_host/git/cppitertools.git"
|
||||||
|
["fmt"]="http://$local_cache_host/git/fmt.git"
|
||||||
["rapidcheck"]="http://$local_cache_host/git/rapidcheck.git"
|
["rapidcheck"]="http://$local_cache_host/git/rapidcheck.git"
|
||||||
["gbenchmark"]="http://$local_cache_host/git/benchmark.git"
|
["gbenchmark"]="http://$local_cache_host/git/benchmark.git"
|
||||||
["gtest"]="http://$local_cache_host/git/googletest.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"
|
["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"
|
["rocksdb"]="http://$local_cache_host/git/rocksdb.git"
|
||||||
["mgclient"]="http://$local_cache_host/git/mgclient.git"
|
["mgclient"]="http://$local_cache_host/git/mgclient.git"
|
||||||
["pymgclient"]="http://$local_cache_host/git/pymgclient.git"
|
["pymgclient"]="http://$local_cache_host/git/pymgclient.git"
|
||||||
["mgconsole"]="http://$local_cache_host/git/mgconsole.git"
|
["mgconsole"]="http://$local_cache_host/git/mgconsole.git"
|
||||||
["spdlog"]="http://$local_cache_host/git/spdlog"
|
["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"
|
["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"
|
["neo4j"]="http://$local_cache_host/file/neo4j-community-3.2.3-unix.tar.gz"
|
||||||
["librdkafka"]="http://$local_cache_host/git/librdkafka.git"
|
["librdkafka"]="http://$local_cache_host/git/librdkafka.git"
|
||||||
["protobuf"]="http://$local_cache_host/git/protobuf.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"
|
["pulsar"]="http://$local_cache_host/git/pulsar.git"
|
||||||
["librdtsc"]="http://$local_cache_host/git/librdtsc.git"
|
["librdtsc"]="http://$local_cache_host/git/librdtsc.git"
|
||||||
)
|
)
|
||||||
@@ -132,19 +138,25 @@ declare -A secondary_urls=(
|
|||||||
["antlr4-code"]="https://github.com/antlr/antlr4.git"
|
["antlr4-code"]="https://github.com/antlr/antlr4.git"
|
||||||
["antlr4-generator"]="http://www.antlr.org/download/antlr-4.9.2-complete.jar"
|
["antlr4-generator"]="http://www.antlr.org/download/antlr-4.9.2-complete.jar"
|
||||||
["cppitertools"]="https://github.com/ryanhaining/cppitertools.git"
|
["cppitertools"]="https://github.com/ryanhaining/cppitertools.git"
|
||||||
|
["fmt"]="https://github.com/fmtlib/fmt.git"
|
||||||
["rapidcheck"]="https://github.com/emil-e/rapidcheck.git"
|
["rapidcheck"]="https://github.com/emil-e/rapidcheck.git"
|
||||||
["gbenchmark"]="https://github.com/google/benchmark.git"
|
["gbenchmark"]="https://github.com/google/benchmark.git"
|
||||||
["gtest"]="https://github.com/google/googletest.git"
|
["gtest"]="https://github.com/google/googletest.git"
|
||||||
|
["gflags"]="https://github.com/memgraph/gflags.git"
|
||||||
["libbcrypt"]="https://github.com/rg3/libbcrypt"
|
["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"
|
["rocksdb"]="https://github.com/facebook/rocksdb.git"
|
||||||
["mgclient"]="https://github.com/memgraph/mgclient.git"
|
["mgclient"]="https://github.com/memgraph/mgclient.git"
|
||||||
["pymgclient"]="https://github.com/memgraph/pymgclient.git"
|
["pymgclient"]="https://github.com/memgraph/pymgclient.git"
|
||||||
["mgconsole"]="http://github.com/memgraph/mgconsole.git"
|
["mgconsole"]="http://github.com/memgraph/mgconsole.git"
|
||||||
["spdlog"]="https://github.com/gabime/spdlog"
|
["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"
|
["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"
|
["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"
|
["librdkafka"]="https://github.com/edenhill/librdkafka.git"
|
||||||
["protobuf"]="https://github.com/protocolbuffers/protobuf.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"
|
["pulsar"]="https://github.com/apache/pulsar.git"
|
||||||
["librdtsc"]="https://github.com/gabrieleara/librdtsc.git"
|
["librdtsc"]="https://github.com/gabrieleara/librdtsc.git"
|
||||||
)
|
)
|
||||||
@@ -199,8 +211,8 @@ git apply ../rocksdb.patch
|
|||||||
popd
|
popd
|
||||||
|
|
||||||
# mgclient
|
# mgclient
|
||||||
mgclient_tag="96e95c6845463cbe88948392be58d26da0d5ffd3" # (2022-02-08)
|
mgclient_tag="v1.3.0" # (2021-09-23)
|
||||||
repo_clone_try_double "${primary_urls[mgclient]}" "${secondary_urls[mgclient]}" "mgclient" "$mgclient_tag"
|
repo_clone_try_double "${primary_urls[mgclient]}" "${secondary_urls[mgclient]}" "mgclient" "$mgclient_tag" true
|
||||||
sed -i 's/\${CMAKE_INSTALL_LIBDIR}/lib/' mgclient/src/CMakeLists.txt
|
sed -i 's/\${CMAKE_INSTALL_LIBDIR}/lib/' mgclient/src/CMakeLists.txt
|
||||||
|
|
||||||
# pymgclient
|
# pymgclient
|
||||||
|
|||||||
@@ -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
|
3. using the Licensed Work to create a work or solution
|
||||||
which competes (or might reasonably be expected to
|
which competes (or might reasonably be expected to
|
||||||
compete) with the Licensed Work.
|
compete) with the Licensed Work.
|
||||||
CHANGE DATE: 2026-27-04
|
CHANGE DATE: 2025-12-08
|
||||||
CHANGE LICENSE: Apache License, Version 2.0
|
CHANGE LICENSE: Apache License, Version 2.0
|
||||||
|
|
||||||
For information about alternative licensing arrangements, please visit: https://memgraph.com/legal.
|
For information about alternative licensing arrangements, please visit: https://memgraph.com/legal.
|
||||||
|
|||||||
@@ -7,11 +7,13 @@ import copy
|
|||||||
|
|
||||||
|
|
||||||
@mgp.read_proc
|
@mgp.read_proc
|
||||||
def procedure(
|
def procedure(context: mgp.ProcCtx,
|
||||||
context: mgp.ProcCtx,
|
required_arg: mgp.Nullable[mgp.Any],
|
||||||
required_arg: mgp.Nullable[mgp.Any],
|
optional_arg: mgp.Nullable[mgp.Any] = None
|
||||||
optional_arg: mgp.Nullable[mgp.Any] = None,
|
) -> mgp.Record(args=list,
|
||||||
) -> mgp.Record(args=list, vertex_count=int, avg_degree=mgp.Number, props=mgp.Nullable[mgp.Map]):
|
vertex_count=int,
|
||||||
|
avg_degree=mgp.Number,
|
||||||
|
props=mgp.Nullable[mgp.Map]):
|
||||||
"""
|
"""
|
||||||
This example procedure returns 4 fields.
|
This example procedure returns 4 fields.
|
||||||
|
|
||||||
@@ -35,7 +37,7 @@ def procedure(
|
|||||||
if isinstance(required_arg, (mgp.Edge, mgp.Vertex)):
|
if isinstance(required_arg, (mgp.Edge, mgp.Vertex)):
|
||||||
props = dict(required_arg.properties.items())
|
props = dict(required_arg.properties.items())
|
||||||
elif isinstance(required_arg, mgp.Path):
|
elif isinstance(required_arg, mgp.Path):
|
||||||
(start_vertex,) = required_arg.vertices
|
start_vertex, = required_arg.vertices
|
||||||
props = dict(start_vertex.properties.items())
|
props = dict(start_vertex.properties.items())
|
||||||
# Count the vertices and edges in the database; this may take a while.
|
# Count the vertices and edges in the database; this may take a while.
|
||||||
vertex_count = 0
|
vertex_count = 0
|
||||||
@@ -49,13 +51,15 @@ def procedure(
|
|||||||
# Copy the received arguments to make it equivalent to the C example.
|
# Copy the received arguments to make it equivalent to the C example.
|
||||||
args_copy = [copy.deepcopy(required_arg), copy.deepcopy(optional_arg)]
|
args_copy = [copy.deepcopy(required_arg), copy.deepcopy(optional_arg)]
|
||||||
# Multiple rows can be produced by returning an iterable of mgp.Record.
|
# 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
|
@mgp.write_proc
|
||||||
def write_procedure(
|
def write_procedure(context: mgp.ProcCtx,
|
||||||
context: mgp.ProcCtx, property_name: str, property_value: mgp.Nullable[mgp.Any]
|
property_name: str,
|
||||||
) -> mgp.Record(created_vertex=mgp.Vertex):
|
property_value: mgp.Nullable[mgp.Any]
|
||||||
|
) -> mgp.Record(created_vertex=mgp.Vertex):
|
||||||
"""
|
"""
|
||||||
This example procedure creates a new vertex with the specified property
|
This example procedure creates a new vertex with the specified property
|
||||||
and connects it to all existing vertex which has the same property with
|
and connects it to all existing vertex which has the same property with
|
||||||
|
|||||||
@@ -4,17 +4,15 @@ from collections import OrderedDict
|
|||||||
from itertools import chain, repeat
|
from itertools import chain, repeat
|
||||||
from inspect import cleandoc
|
from inspect import cleandoc
|
||||||
from typing import List, Tuple
|
from typing import List, Tuple
|
||||||
|
|
||||||
try:
|
try:
|
||||||
import networkx as nx
|
import networkx as nx
|
||||||
except ImportError as import_error:
|
except ImportError as import_error:
|
||||||
sys.stderr.write(
|
sys.stderr.write((
|
||||||
(
|
'\n'
|
||||||
"\n"
|
'NOTE: Please install networkx to be able to use graph_analyzer '
|
||||||
"NOTE: Please install networkx to be able to use graph_analyzer "
|
'module. Using Python:\n'
|
||||||
"module. Using Python:\n" + sys.version + "\n"
|
+ sys.version +
|
||||||
)
|
'\n'))
|
||||||
)
|
|
||||||
raise import_error
|
raise import_error
|
||||||
# Imported last because it also depends on networkx.
|
# Imported last because it also depends on networkx.
|
||||||
from mgp_networkx import MemgraphMultiDiGraph # noqa E402
|
from mgp_networkx import MemgraphMultiDiGraph # noqa E402
|
||||||
@@ -25,14 +23,16 @@ _MAX_LIST_SIZE = 10
|
|||||||
|
|
||||||
@mgp.read_proc
|
@mgp.read_proc
|
||||||
def help() -> mgp.Record(name=str, value=str):
|
def help() -> mgp.Record(name=str, value=str):
|
||||||
"""Shows manual page for graph_analyzer."""
|
'''Shows manual page for graph_analyzer.'''
|
||||||
records = []
|
records = []
|
||||||
|
|
||||||
def make_records(name, doc):
|
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):
|
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():
|
for m, v in _get_analysis_mapping().items():
|
||||||
records.extend(make_records("Analysis '{}'".format(m), v.__doc__))
|
records.extend(make_records("Analysis '{}'".format(m), v.__doc__))
|
||||||
@@ -41,8 +41,10 @@ def help() -> mgp.Record(name=str, value=str):
|
|||||||
|
|
||||||
|
|
||||||
@mgp.read_proc
|
@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.
|
Shows graph information.
|
||||||
|
|
||||||
In case of multiple results, only the first 10 will be shown.
|
In case of multiple results, only the first 10 will be shown.
|
||||||
@@ -55,20 +57,19 @@ def analyze(context: mgp.ProcCtx, analyses: mgp.Nullable[List[str]] = None) -> m
|
|||||||
|
|
||||||
Example call (with parameter):
|
Example call (with parameter):
|
||||||
CALL graph_analyzer.analyze(['nodes', 'edges']) YIELD *;
|
CALL graph_analyzer.analyze(['nodes', 'edges']) YIELD *;
|
||||||
"""
|
'''
|
||||||
g = MemgraphMultiDiGraph(ctx=context)
|
g = MemgraphMultiDiGraph(ctx=context)
|
||||||
recs = _analyze_graph(context, g, analyses)
|
recs = _analyze_graph(context, g, analyses)
|
||||||
return [mgp.Record(name=name, value=value) for name, value in recs]
|
return [mgp.Record(name=name, value=value) for name, value in recs]
|
||||||
|
|
||||||
|
|
||||||
@mgp.read_proc
|
@mgp.read_proc
|
||||||
def analyze_subgraph(
|
def analyze_subgraph(context: mgp.ProcCtx,
|
||||||
context: mgp.ProcCtx,
|
vertices: mgp.List[mgp.Vertex],
|
||||||
vertices: mgp.List[mgp.Vertex],
|
edges: mgp.List[mgp.Edge],
|
||||||
edges: mgp.List[mgp.Edge],
|
analyses: mgp.Nullable[List[str]] = None
|
||||||
analyses: mgp.Nullable[List[str]] = None,
|
) -> mgp.Record(name=str, value=str):
|
||||||
) -> mgp.Record(name=str, value=str):
|
'''
|
||||||
"""
|
|
||||||
Shows subgraph information.
|
Shows subgraph information.
|
||||||
|
|
||||||
In case of multiple results, only the first 10 will be shown.
|
In case of multiple results, only the first 10 will be shown.
|
||||||
@@ -90,40 +91,36 @@ def analyze_subgraph(
|
|||||||
CALL graph_analyzer.analyze_subgraph(nodes, edges, ['nodes', 'edges'])
|
CALL graph_analyzer.analyze_subgraph(nodes, edges, ['nodes', 'edges'])
|
||||||
YIELD *
|
YIELD *
|
||||||
RETURN name, value;
|
RETURN name, value;
|
||||||
"""
|
'''
|
||||||
vertices, edges = map(set, [vertices, edges])
|
vertices, edges = map(set, [vertices, edges])
|
||||||
g = nx.subgraph_view(
|
g = nx.subgraph_view(
|
||||||
MemgraphMultiDiGraph(ctx=context),
|
MemgraphMultiDiGraph(ctx=context),
|
||||||
lambda n: n in vertices,
|
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)
|
recs = _analyze_graph(context, g, analyses)
|
||||||
return [mgp.Record(name=name, value=value) for name, value in recs]
|
return [mgp.Record(name=name, value=value) for name, value in recs]
|
||||||
|
|
||||||
|
|
||||||
def _get_analysis_mapping():
|
def _get_analysis_mapping():
|
||||||
return OrderedDict(
|
return OrderedDict([
|
||||||
[
|
('nodes', _number_of_nodes),
|
||||||
("nodes", _number_of_nodes),
|
('edges', _number_of_edges),
|
||||||
("edges", _number_of_edges),
|
('bridges', _bridges),
|
||||||
("bridges", _bridges),
|
('articulation_points', _articulation_points),
|
||||||
("articulation_points", _articulation_points),
|
('avg_degree', _avg_degree),
|
||||||
("avg_degree", _avg_degree),
|
('sorted_nodes_degree', _sorted_nodes_degree),
|
||||||
("sorted_nodes_degree", _sorted_nodes_degree),
|
('self_loops', _self_loops),
|
||||||
("self_loops", _self_loops),
|
('is_bipartite', _is_bipartite),
|
||||||
("is_bipartite", _is_bipartite),
|
('is_planar', _is_planar),
|
||||||
("is_planar", _is_planar),
|
('is_biconnected: ', _is_biconnected),
|
||||||
("is_biconnected: ", _is_biconnected),
|
('is_weakly_connected', _is_weakly_connected),
|
||||||
("is_weakly_connected", _is_weakly_connected),
|
('number_of_weakly_components', _weakly_components),
|
||||||
("number_of_weakly_components", _weakly_components),
|
('is_strongly_connected', _is_strongly_connected),
|
||||||
("is_strongly_connected", _is_strongly_connected),
|
('strongly_components', _strongly_components),
|
||||||
("strongly_components", _strongly_components),
|
('is_dag', _is_dag),
|
||||||
("is_dag", _is_dag),
|
('is_eulerian', _is_eulerian),
|
||||||
("is_eulerian", _is_eulerian),
|
('is_forest', _is_forest),
|
||||||
("is_forest", _is_forest),
|
('is_tree', _is_tree)])
|
||||||
("is_tree", _is_tree),
|
|
||||||
]
|
|
||||||
)
|
|
||||||
|
|
||||||
|
|
||||||
def _get_analysis_func(name: str):
|
def _get_analysis_func(name: str):
|
||||||
@@ -135,15 +132,20 @@ def _get_analysis_funcs():
|
|||||||
return _get_analysis_mapping().values()
|
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 = []
|
records = []
|
||||||
for index, f in enumerate(functions):
|
for index, f in enumerate(functions):
|
||||||
context.check_must_abort()
|
context.check_must_abort()
|
||||||
if f is None:
|
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)
|
name, value = f(g)
|
||||||
if isinstance(value, (list, set, tuple)):
|
if isinstance(value, (list, set, tuple)):
|
||||||
value = list(value)[:_MAX_LIST_SIZE]
|
value = list(value)[:_MAX_LIST_SIZE]
|
||||||
@@ -153,120 +155,126 @@ def _analyze_graph(context: mgp.ProcCtx, g: nx.MultiDiGraph, analyses: List[str]
|
|||||||
|
|
||||||
|
|
||||||
def _number_of_nodes(g: nx.MultiDiGraph) -> Tuple[str, int]:
|
def _number_of_nodes(g: nx.MultiDiGraph) -> Tuple[str, int]:
|
||||||
"""Returns number of nodes."""
|
'''Returns number of nodes.'''
|
||||||
return "Number of nodes", nx.number_of_nodes(g)
|
return 'Number of nodes', nx.number_of_nodes(g)
|
||||||
|
|
||||||
|
|
||||||
def _number_of_edges(g: nx.MultiDiGraph) -> Tuple[str, int]:
|
def _number_of_edges(g: nx.MultiDiGraph) -> Tuple[str, int]:
|
||||||
"""Returns number of edges."""
|
'''Returns number of edges.'''
|
||||||
return "Number of edges", nx.number_of_edges(g)
|
return 'Number of edges', nx.number_of_edges(g)
|
||||||
|
|
||||||
|
|
||||||
def _avg_degree(g: nx.MultiDiGraph) -> Tuple[str, float]:
|
def _avg_degree(g: nx.MultiDiGraph) -> Tuple[str, float]:
|
||||||
"""Returns average degree."""
|
'''Returns average degree.'''
|
||||||
_, number_of_nodes = _number_of_nodes(g)
|
_, number_of_nodes = _number_of_nodes(g)
|
||||||
_, number_of_edges = _number_of_edges(g)
|
_, number_of_edges = _number_of_edges(g)
|
||||||
avg_degree = 0 if number_of_nodes == 0 else number_of_edges / number_of_nodes
|
avg_degree = (0 if number_of_nodes == 0
|
||||||
return "Average degree", avg_degree
|
else number_of_edges / number_of_nodes)
|
||||||
|
return 'Average degree', avg_degree
|
||||||
|
|
||||||
|
|
||||||
def _sorted_nodes_degree(g: nx.MultiDiGraph) -> Tuple[str, List[int]]:
|
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 = [(n, g.degree(n)) for n in g.nodes()]
|
||||||
nodes_degree.sort(key=lambda x: x[1], reverse=True)
|
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]:
|
def _self_loops(g: nx.MultiDiGraph) -> Tuple[str, int]:
|
||||||
"""Returns number of self loops."""
|
'''Returns number of self loops.'''
|
||||||
return "Self loops", sum((1 if e[0] == e[1] else 0 for e in g.edges()))
|
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]:
|
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)
|
_, number_of_nodes = _number_of_nodes(g)
|
||||||
ret = False if number_of_nodes == 0 else nx.algorithms.bipartite.basic.is_bipartite(g)
|
ret = (False if number_of_nodes == 0
|
||||||
return "Is bipartite", ret
|
else nx.algorithms.bipartite.basic.is_bipartite(g))
|
||||||
|
return 'Is bipartite', ret
|
||||||
|
|
||||||
|
|
||||||
def _is_planar(g: nx.MultiDiGraph) -> Tuple[str, bool]:
|
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)
|
_, number_of_nodes = _number_of_nodes(g)
|
||||||
ret = False if number_of_nodes == 0 else nx.algorithms.planarity.check_planarity(g)[0]
|
ret = (False if number_of_nodes == 0
|
||||||
return "Is planar", ret
|
else nx.algorithms.planarity.check_planarity(g)[0])
|
||||||
|
return 'Is planar', ret
|
||||||
|
|
||||||
|
|
||||||
def _is_biconnected(g: nx.MultiDiGraph) -> Tuple[str, bool]:
|
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)
|
_, number_of_nodes = _number_of_nodes(g)
|
||||||
ret = False if number_of_nodes == 0 else nx.is_biconnected(nx.MultiDiGraph.to_undirected(g))
|
ret = (False if number_of_nodes == 0
|
||||||
return "Is biconnected", ret
|
else nx.is_biconnected(nx.MultiDiGraph.to_undirected(g)))
|
||||||
|
return 'Is biconnected', ret
|
||||||
|
|
||||||
|
|
||||||
def _is_weakly_connected(g: nx.MultiDiGraph) -> Tuple[str, bool]:
|
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)
|
_, number_of_nodes = _number_of_nodes(g)
|
||||||
ret = False if number_of_nodes == 0 else nx.is_weakly_connected(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]:
|
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)
|
_, number_of_nodes = _number_of_nodes(g)
|
||||||
ret = False if number_of_nodes == 0 else nx.is_strongly_connected(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]:
|
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)
|
_, number_of_nodes = _number_of_nodes(g)
|
||||||
ret = False if number_of_nodes == 0 else nx.algorithms.dag.is_directed_acyclic_graph(g)
|
ret = (False if number_of_nodes == 0
|
||||||
return "Is DAG", ret
|
else nx.algorithms.dag.is_directed_acyclic_graph(g))
|
||||||
|
return 'Is DAG', ret
|
||||||
|
|
||||||
|
|
||||||
def _is_eulerian(g: nx.MultiDiGraph) -> Tuple[str, bool]:
|
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)
|
_, number_of_nodes = _number_of_nodes(g)
|
||||||
ret = False if number_of_nodes == 0 else nx.algorithms.euler.is_eulerian(g)
|
ret = (False if number_of_nodes == 0
|
||||||
return "Is eulerian", ret
|
else nx.algorithms.euler.is_eulerian(g))
|
||||||
|
return 'Is eulerian', ret
|
||||||
|
|
||||||
|
|
||||||
def _is_forest(g: nx.MultiDiGraph) -> Tuple[str, bool]:
|
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)
|
_, number_of_nodes = _number_of_nodes(g)
|
||||||
ret = False if number_of_nodes == 0 else nx.algorithms.tree.recognition.is_forest(g)
|
ret = (False if number_of_nodes == 0
|
||||||
return "Is forest", ret
|
else nx.algorithms.tree.recognition.is_forest(g))
|
||||||
|
return 'Is forest', ret
|
||||||
|
|
||||||
|
|
||||||
def _is_tree(g: nx.MultiDiGraph) -> Tuple[str, bool]:
|
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)
|
_, number_of_nodes = _number_of_nodes(g)
|
||||||
ret = False if number_of_nodes == 0 else nx.algorithms.tree.recognition.is_tree(g)
|
ret = (False if number_of_nodes == 0
|
||||||
return "Is tree", ret
|
else nx.algorithms.tree.recognition.is_tree(g))
|
||||||
|
return 'Is tree', ret
|
||||||
|
|
||||||
|
|
||||||
def _bridges(g: nx.MultiDiGraph) -> Tuple[str, int]:
|
def _bridges(g: nx.MultiDiGraph) -> Tuple[str, int]:
|
||||||
"""Returns number of bridges, multiple edges between same nodes are
|
'''Returns number of bridges, multiple edges between same nodes are
|
||||||
mapped to one edge."""
|
mapped to one edge.'''
|
||||||
return "Number of bridges", sum(1 for _ in nx.bridges(nx.Graph(g)))
|
return 'Number of bridges', sum(1 for _ in nx.bridges(nx.Graph(g)))
|
||||||
|
|
||||||
|
|
||||||
def _articulation_points(g: nx.MultiDiGraph):
|
def _articulation_points(g: nx.MultiDiGraph):
|
||||||
"""Returns number of articulation points."""
|
'''Returns number of articulation points.'''
|
||||||
undirected = nx.MultiDiGraph.to_undirected(g)
|
undirected = nx.MultiDiGraph.to_undirected(g)
|
||||||
return (
|
return ('Number of articulation points',
|
||||||
"Number of articulation points",
|
sum(1 for _ in nx.articulation_points(undirected)))
|
||||||
sum(1 for _ in nx.articulation_points(undirected)),
|
|
||||||
)
|
|
||||||
|
|
||||||
|
|
||||||
def _weakly_components(g: nx.MultiDiGraph):
|
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)
|
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):
|
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)
|
comps = nx.algorithms.components.number_strongly_connected_components(g)
|
||||||
return "Number of strongly connected components", comps
|
return 'Number of strongly connected components', comps
|
||||||
|
|||||||
@@ -1,22 +1,20 @@
|
|||||||
import sys
|
import sys
|
||||||
import mgp
|
import mgp
|
||||||
import collections
|
import collections
|
||||||
|
|
||||||
try:
|
try:
|
||||||
import networkx as nx
|
import networkx as nx
|
||||||
except ImportError as import_error:
|
except ImportError as import_error:
|
||||||
sys.stderr.write(
|
sys.stderr.write((
|
||||||
(
|
'\n'
|
||||||
"\n"
|
'NOTE: Please install networkx to be able to use Memgraph NetworkX '
|
||||||
"NOTE: Please install networkx to be able to use Memgraph NetworkX "
|
'wrappers. Using Python:\n'
|
||||||
"wrappers. Using Python:\n" + sys.version + "\n"
|
+ sys.version +
|
||||||
)
|
'\n'))
|
||||||
)
|
|
||||||
raise import_error
|
raise import_error
|
||||||
|
|
||||||
|
|
||||||
class MemgraphAdjlistOuterDict(collections.abc.Mapping):
|
class MemgraphAdjlistOuterDict(collections.abc.Mapping):
|
||||||
__slots__ = ("_ctx", "_succ", "_multi")
|
__slots__ = ('_ctx', '_succ', '_multi')
|
||||||
|
|
||||||
def __init__(self, ctx, succ=True, multi=True):
|
def __init__(self, ctx, succ=True, multi=True):
|
||||||
self._ctx = ctx
|
self._ctx = ctx
|
||||||
@@ -26,7 +24,8 @@ class MemgraphAdjlistOuterDict(collections.abc.Mapping):
|
|||||||
def __getitem__(self, key):
|
def __getitem__(self, key):
|
||||||
if key not in self:
|
if key not in self:
|
||||||
raise KeyError
|
raise KeyError
|
||||||
return MemgraphAdjlistInnerDict(key, succ=self._succ, multi=self._multi)
|
return MemgraphAdjlistInnerDict(key, succ=self._succ,
|
||||||
|
multi=self._multi)
|
||||||
|
|
||||||
def __iter__(self):
|
def __iter__(self):
|
||||||
return iter(self._ctx.graph.vertices)
|
return iter(self._ctx.graph.vertices)
|
||||||
@@ -41,7 +40,7 @@ class MemgraphAdjlistOuterDict(collections.abc.Mapping):
|
|||||||
|
|
||||||
|
|
||||||
class MemgraphAdjlistInnerDict(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):
|
def __init__(self, node, succ=True, multi=True):
|
||||||
self._node = node
|
self._node = node
|
||||||
@@ -72,26 +71,31 @@ class MemgraphAdjlistInnerDict(collections.abc.Mapping):
|
|||||||
def _get_neighbors(self):
|
def _get_neighbors(self):
|
||||||
if not self._neighbors:
|
if not self._neighbors:
|
||||||
if self._succ:
|
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:
|
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
|
return self._neighbors
|
||||||
|
|
||||||
def _get_edge(self, neighbor):
|
def _get_edge(self, neighbor):
|
||||||
if self._succ:
|
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:
|
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
|
assert len(edge) >= 1
|
||||||
if 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]
|
return edge[0]
|
||||||
|
|
||||||
|
|
||||||
class MemgraphEdgeKeyDict(collections.abc.Mapping):
|
class MemgraphEdgeKeyDict(collections.abc.Mapping):
|
||||||
__slots__ = ("_node", "_neighbor", "_succ", "_edges")
|
__slots__ = ('_node', '_neighbor', '_succ', '_edges')
|
||||||
|
|
||||||
def __init__(self, node, neighbor, succ=True):
|
def __init__(self, node, neighbor, succ=True):
|
||||||
self._node = node
|
self._node = node
|
||||||
@@ -118,14 +122,18 @@ class MemgraphEdgeKeyDict(collections.abc.Mapping):
|
|||||||
def _get_edges(self):
|
def _get_edges(self):
|
||||||
if not self._edges:
|
if not self._edges:
|
||||||
if self._succ:
|
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:
|
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
|
return self._edges
|
||||||
|
|
||||||
|
|
||||||
class UnhashableProperties(collections.abc.Mapping):
|
class UnhashableProperties(collections.abc.Mapping):
|
||||||
__slots__ = "_properties"
|
__slots__ = ('_properties')
|
||||||
|
|
||||||
def __init__(self, properties):
|
def __init__(self, properties):
|
||||||
self._properties = properties
|
self._properties = properties
|
||||||
@@ -147,7 +155,7 @@ class UnhashableProperties(collections.abc.Mapping):
|
|||||||
|
|
||||||
|
|
||||||
class MemgraphNodeDict(collections.abc.Mapping):
|
class MemgraphNodeDict(collections.abc.Mapping):
|
||||||
__slots__ = ("_ctx",)
|
__slots__ = ('_ctx',)
|
||||||
|
|
||||||
def __init__(self, ctx):
|
def __init__(self, ctx):
|
||||||
self._ctx = ctx
|
self._ctx = ctx
|
||||||
@@ -179,7 +187,8 @@ class MemgraphNodeDict(collections.abc.Mapping):
|
|||||||
|
|
||||||
|
|
||||||
class MemgraphDiGraphBase:
|
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
|
# NOTE: We assume that our graph will never be given any initial data
|
||||||
# because we already pull our data from the Memgraph database. This
|
# because we already pull our data from the Memgraph database. This
|
||||||
# assert is triggered by certain NetworkX procedures because they
|
# assert is triggered by certain NetworkX procedures because they
|
||||||
@@ -192,30 +201,23 @@ class MemgraphDiGraphBase:
|
|||||||
# modify the graph's internal attributes and don't try to populate it
|
# modify the graph's internal attributes and don't try to populate it
|
||||||
# with initial data or modify 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.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.adjlist_inner_dict_factory = self._error
|
||||||
self.edge_key_dict_factory = self._error
|
self.edge_key_dict_factory = self._error
|
||||||
self.edge_attr_dict_factory = self._error
|
self.edge_attr_dict_factory = self._error
|
||||||
|
|
||||||
# NOTE: We forbid any mutating operations because our graph is
|
# NOTE: We forbid any mutating operations because our graph is
|
||||||
# immutable and pulls its data from the Memgraph database.
|
# immutable and pulls its data from the Memgraph database.
|
||||||
for f in [
|
for f in ['add_node', 'add_nodes_from', 'remove_node',
|
||||||
"add_node",
|
'remove_nodes_from', 'add_edge', 'add_edges_from',
|
||||||
"add_nodes_from",
|
'add_weighted_edges_from', 'new_edge_key', 'remove_edge',
|
||||||
"remove_node",
|
'remove_edges_from', 'update', 'clear']:
|
||||||
"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())
|
setattr(self, f, lambda *args, **kwargs: self._error())
|
||||||
|
|
||||||
super().__init__(None, **kwargs)
|
super().__init__(None, **kwargs)
|
||||||
@@ -229,29 +231,33 @@ class MemgraphDiGraphBase:
|
|||||||
self._pred = MemgraphAdjlistOuterDict(ctx, succ=False, multi=multi)
|
self._pred = MemgraphAdjlistOuterDict(ctx, succ=False, multi=multi)
|
||||||
|
|
||||||
def _error(self):
|
def _error(self):
|
||||||
raise RuntimeError("Modification operations are not supported")
|
raise RuntimeError('Modification operations are not supported')
|
||||||
|
|
||||||
|
|
||||||
class MemgraphMultiDiGraph(MemgraphDiGraphBase, nx.MultiDiGraph):
|
class MemgraphMultiDiGraph(MemgraphDiGraphBase, nx.MultiDiGraph):
|
||||||
def __init__(self, incoming_graph_data=None, ctx=None, **kwargs):
|
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):
|
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):
|
class MemgraphDiGraph(MemgraphDiGraphBase, nx.DiGraph):
|
||||||
def __init__(self, incoming_graph_data=None, ctx=None, **kwargs):
|
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):
|
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):
|
class PropertiesDictionary(collections.abc.Mapping):
|
||||||
__slots__ = ("_ctx", "_prop", "_len")
|
__slots__ = ('_ctx', '_prop', '_len')
|
||||||
|
|
||||||
def __init__(self, ctx, prop):
|
def __init__(self, ctx, prop):
|
||||||
self._ctx = ctx
|
self._ctx = ctx
|
||||||
@@ -264,7 +270,8 @@ class PropertiesDictionary(collections.abc.Mapping):
|
|||||||
try:
|
try:
|
||||||
return vertex.properties[self._prop]
|
return vertex.properties[self._prop]
|
||||||
except KeyError:
|
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):
|
def __iter__(self):
|
||||||
for v in self._ctx.graph.vertices:
|
for v in self._ctx.graph.vertices:
|
||||||
|
|||||||
File diff suppressed because it is too large
Load Diff
@@ -1,20 +1,23 @@
|
|||||||
import sys
|
import sys
|
||||||
import mgp
|
import mgp
|
||||||
|
|
||||||
try:
|
try:
|
||||||
import networkx as nx
|
import networkx as nx
|
||||||
except ImportError as import_error:
|
except ImportError as import_error:
|
||||||
sys.stderr.write(
|
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
|
raise import_error
|
||||||
|
|
||||||
|
|
||||||
@mgp.read_proc
|
@mgp.read_proc
|
||||||
def get_components(
|
def get_components(vertices: mgp.List[mgp.Vertex],
|
||||||
vertices: mgp.List[mgp.Vertex], edges: mgp.List[mgp.Edge]
|
edges: mgp.List[mgp.Edge]
|
||||||
) -> mgp.Record(n_components=int, components=mgp.List[mgp.List[mgp.Vertex]]):
|
) -> mgp.Record(n_components=int,
|
||||||
"""
|
components=mgp.List[mgp.List[mgp.Vertex]]):
|
||||||
|
'''
|
||||||
This procedure finds weakly connected components of a given subgraph of a
|
This procedure finds weakly connected components of a given subgraph of a
|
||||||
directed graph.
|
directed graph.
|
||||||
|
|
||||||
@@ -38,7 +41,7 @@ def get_components(
|
|||||||
WITH collect(n) AS nodes, collect(e) AS edges
|
WITH collect(n) AS nodes, collect(e) AS edges
|
||||||
CALL wcc.get_components(nodes, edges) YIELD *
|
CALL wcc.get_components(nodes, edges) YIELD *
|
||||||
RETURN n_components, components;
|
RETURN n_components, components;
|
||||||
"""
|
'''
|
||||||
g = nx.DiGraph()
|
g = nx.DiGraph()
|
||||||
g.add_nodes_from(vertices)
|
g.add_nodes_from(vertices)
|
||||||
g.add_edges_from([(edge.from_vertex, edge.to_vertex) for edge in edges])
|
g.add_edges_from([(edge.from_vertex, edge.to_vertex) for edge in edges])
|
||||||
|
|||||||
@@ -10,14 +10,6 @@ set(CPACK_PACKAGE_VENDOR "Memgraph Ltd.")
|
|||||||
set(CPACK_PACKAGE_DESCRIPTION_SUMMARY
|
set(CPACK_PACKAGE_DESCRIPTION_SUMMARY
|
||||||
"High performance, in-memory, transactional graph database")
|
"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
|
# DEB specific
|
||||||
# Instead of using "name <email>" format, we use "email (name)" to prevent
|
# 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)
|
# errors due to full stop, '.' at the end of "Ltd". (See: RFC 822)
|
||||||
@@ -25,7 +17,7 @@ set(CPACK_DEBIAN_PACKAGE_MAINTAINER "tech@memgraph.com (Memgraph Ltd.)")
|
|||||||
set(CPACK_DEBIAN_PACKAGE_SECTION non-free/database)
|
set(CPACK_DEBIAN_PACKAGE_SECTION non-free/database)
|
||||||
set(CPACK_DEBIAN_PACKAGE_HOMEPAGE https://memgraph.com)
|
set(CPACK_DEBIAN_PACKAGE_HOMEPAGE https://memgraph.com)
|
||||||
set(CPACK_DEBIAN_PACKAGE_VERSION "${MEMGRAPH_VERSION_DEB}")
|
set(CPACK_DEBIAN_PACKAGE_VERSION "${MEMGRAPH_VERSION_DEB}")
|
||||||
set(CPACK_DEBIAN_FILE_NAME "memgraph_${MEMGRAPH_VERSION_DEB}_${MG_ARCH_EXTENSION_DEB}.deb")
|
set(CPACK_DEBIAN_FILE_NAME "memgraph_${MEMGRAPH_VERSION_DEB}_amd64.deb")
|
||||||
set(CPACK_DEBIAN_PACKAGE_CONTROL_EXTRA
|
set(CPACK_DEBIAN_PACKAGE_CONTROL_EXTRA
|
||||||
"${CMAKE_CURRENT_SOURCE_DIR}/debian/conffiles;"
|
"${CMAKE_CURRENT_SOURCE_DIR}/debian/conffiles;"
|
||||||
"${CMAKE_CURRENT_SOURCE_DIR}/debian/copyright;"
|
"${CMAKE_CURRENT_SOURCE_DIR}/debian/copyright;"
|
||||||
@@ -41,20 +33,21 @@ set(CPACK_DEBIAN_PACKAGE_DESCRIPTION "${CPACK_PACKAGE_DESCRIPTION_SUMMARY}
|
|||||||
applications driver by real-time connected data.")
|
applications driver by real-time connected data.")
|
||||||
# Add `openssl` package to dependencies list. Used to generate SSL certificates.
|
# Add `openssl` package to dependencies list. Used to generate SSL certificates.
|
||||||
# We also depend on `python3` because we embed it in Memgraph.
|
# We also depend on `python3` because we embed it in Memgraph.
|
||||||
set(CPACK_DEBIAN_PACKAGE_DEPENDS "openssl (>= 1.1.0), python3 (>= 3.5.0), libstdc++6")
|
set(CPACK_DEBIAN_PACKAGE_DEPENDS "openssl (>= 1.1.0), python3 (>= 3.5.0)")
|
||||||
|
|
||||||
# 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
|
# RPM specific
|
||||||
|
|
||||||
|
set(MG_ARCH_EXTENSION "noarch")
|
||||||
|
|
||||||
|
if (${MG_ARCH} STREQUAL "x86_64")
|
||||||
|
set(MG_ARCH_EXTENSION "x86_64")
|
||||||
|
elseif (${MG_ARCH} STREQUAL "ARM64")
|
||||||
|
set(MG_ARCH_EXTENSION "aarch64")
|
||||||
|
endif()
|
||||||
|
|
||||||
set(CPACK_RPM_PACKAGE_URL https://memgraph.com)
|
set(CPACK_RPM_PACKAGE_URL https://memgraph.com)
|
||||||
set(CPACK_RPM_PACKAGE_VERSION "${MEMGRAPH_VERSION_RPM}")
|
set(CPACK_RPM_PACKAGE_VERSION "${MEMGRAPH_VERSION_RPM}")
|
||||||
set(CPACK_RPM_FILE_NAME "memgraph-${MEMGRAPH_VERSION_RPM}-1.${MG_ARCH_EXTENSION_RPM}.rpm")
|
set(CPACK_RPM_FILE_NAME "memgraph-${MEMGRAPH_VERSION_RPM}-1.${MG_ARCH_EXTENSION}.rpm")
|
||||||
set(CPACK_RPM_EXCLUDE_FROM_AUTO_FILELIST_ADDITION
|
set(CPACK_RPM_EXCLUDE_FROM_AUTO_FILELIST_ADDITION
|
||||||
/var /var/lib /var/log /etc/logrotate.d
|
/var /var/lib /var/log /etc/logrotate.d
|
||||||
/lib /lib/systemd /lib/systemd/system /lib/systemd/system/memgraph.service)
|
/lib /lib/systemd /lib/systemd/system /lib/systemd/system/memgraph.service)
|
||||||
@@ -67,7 +60,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.")
|
the next generation of applications driver by real-time connected data.")
|
||||||
# Add `openssl` package to dependencies list. Used to generate SSL certificates.
|
# Add `openssl` package to dependencies list. Used to generate SSL certificates.
|
||||||
# We also depend on `python3` because we embed it in Memgraph.
|
# 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, libstdc >= 6, logrotate")
|
set(CPACK_RPM_PACKAGE_REQUIRES "openssl >= 1.0.0, curl >= 7.29.0, python3 >= 3.5.0")
|
||||||
|
|
||||||
# All variables must be set before including.
|
# All variables must be set before including.
|
||||||
include(CPack)
|
include(CPack)
|
||||||
|
|||||||
@@ -1,21 +1,19 @@
|
|||||||
FROM debian:bullseye
|
FROM debian:bullseye
|
||||||
# NOTE: If you change the base distro update release/package as well.
|
# NOTE: If you change the base distro update release/package as well.
|
||||||
|
|
||||||
ARG BINARY_NAME
|
ARG release
|
||||||
ARG EXTENSION
|
|
||||||
ARG TARGETARCH
|
|
||||||
|
|
||||||
RUN apt-get update && apt-get install -y \
|
RUN apt-get update && apt-get install -y \
|
||||||
openssl libcurl4 libssl1.1 libseccomp2 python3 libpython3.9 python3-pip \
|
openssl libcurl4 libssl1.1 libseccomp2 python3 libpython3.9 python3-pip \
|
||||||
--no-install-recommends \
|
--no-install-recommends \
|
||||||
&& rm -rf /var/lib/apt/lists/* /tmp/* /var/tmp/*
|
&& rm -rf /var/lib/apt/lists/* /tmp/* /var/tmp/*
|
||||||
|
|
||||||
RUN pip3 install networkx==2.4 numpy==1.21.4 scipy==1.7.3
|
RUN pip3 install networkx==2.4 numpy==1.21.4 scipy==1.7.3
|
||||||
|
|
||||||
COPY "${BINARY_NAME}${TARGETARCH}.${EXTENSION}" /
|
COPY ${release} /
|
||||||
|
|
||||||
# Install memgraph package
|
# Install memgraph package
|
||||||
RUN dpkg -i "${BINARY_NAME}${TARGETARCH}.deb"
|
RUN dpkg -i ${release}
|
||||||
|
|
||||||
# Memgraph listens for Bolt Protocol on this port by default.
|
# Memgraph listens for Bolt Protocol on this port by default.
|
||||||
EXPOSE 7687
|
EXPOSE 7687
|
||||||
|
|||||||
31
release/docker/memgraph_rpm.dockerfile
Normal file
31
release/docker/memgraph_rpm.dockerfile
Normal file
@@ -0,0 +1,31 @@
|
|||||||
|
FROM dokken/centos-stream-9
|
||||||
|
# NOTE: If you change the base distro update release/package as well.
|
||||||
|
|
||||||
|
ARG release
|
||||||
|
|
||||||
|
RUN yum update && yum install -y \
|
||||||
|
openssl libcurl libseccomp python3 python3-pip \
|
||||||
|
--nobest --allowerasing \
|
||||||
|
&& rm -rf /tmp/* \
|
||||||
|
&& yum clean all
|
||||||
|
|
||||||
|
RUN pip3 install networkx==2.4 numpy==1.21.4 scipy==1.7.3
|
||||||
|
|
||||||
|
COPY ${release} /
|
||||||
|
|
||||||
|
# Install memgraph package
|
||||||
|
RUN rpm -i ${release}
|
||||||
|
|
||||||
|
# Memgraph listens for Bolt Protocol on this port by default.
|
||||||
|
EXPOSE 7687
|
||||||
|
# Snapshots and logging volumes
|
||||||
|
VOLUME /var/log/memgraph
|
||||||
|
VOLUME /var/lib/memgraph
|
||||||
|
# Configuration volume
|
||||||
|
VOLUME /etc/memgraph
|
||||||
|
|
||||||
|
USER memgraph
|
||||||
|
WORKDIR /usr/lib/memgraph
|
||||||
|
|
||||||
|
ENTRYPOINT ["/usr/lib/memgraph/memgraph"]
|
||||||
|
CMD [""]
|
||||||
@@ -55,10 +55,7 @@ image_name="memgraph:${version}"
|
|||||||
image_package_name="memgraph-${version}-docker.tar.gz"
|
image_package_name="memgraph-${version}-docker.tar.gz"
|
||||||
|
|
||||||
# Build docker image.
|
# Build docker image.
|
||||||
docker build -t ${image_name} ${tag_latest} -f ${dockerfile_path} \
|
docker build -t ${image_name} ${tag_latest} -f ${dockerfile_path} --build-arg release=${package_name}.${extension} .
|
||||||
--build-arg BINARY_NAME=${package_name} \
|
|
||||||
--build-arg EXTENSION=${extension} \
|
|
||||||
--build-arg TARGETARCH="" .
|
|
||||||
docker save ${image_name} ${latest_image} | gzip > ${image_package_name}
|
docker save ${image_name} ${latest_image} | gzip > ${image_package_name}
|
||||||
rm "${package_name}.${extension}"
|
rm "${package_name}.${extension}"
|
||||||
echo "Built Docker image at '${working_dir}/${image_package_name}'"
|
echo "Built Docker image at '${working_dir}/${image_package_name}'"
|
||||||
|
|||||||
@@ -104,9 +104,7 @@ def retry(retry_limit, timeout=100):
|
|||||||
except Exception:
|
except Exception:
|
||||||
time.sleep(timeout)
|
time.sleep(timeout)
|
||||||
return func(*args, **kwargs)
|
return func(*args, **kwargs)
|
||||||
|
|
||||||
return wrapper
|
return wrapper
|
||||||
|
|
||||||
return inner_func
|
return inner_func
|
||||||
|
|
||||||
|
|
||||||
@@ -165,15 +163,8 @@ def format_version(variant, version, offering, distance=None, shorthash=None, su
|
|||||||
|
|
||||||
# Parse arguments.
|
# Parse arguments.
|
||||||
parser = argparse.ArgumentParser(description="Get the current version of Memgraph.")
|
parser = argparse.ArgumentParser(description="Get the current version of Memgraph.")
|
||||||
parser.add_argument(
|
parser.add_argument("--open-source", action="store_true", help="set the current offering to 'open-source'")
|
||||||
"--open-source",
|
parser.add_argument("version", help="manual version override, if supplied the version isn't " "determined using git")
|
||||||
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("suffix", help="custom suffix for the current version being built")
|
||||||
parser.add_argument(
|
parser.add_argument(
|
||||||
"--variant",
|
"--variant",
|
||||||
@@ -182,9 +173,7 @@ parser.add_argument(
|
|||||||
help="which variant of the version string should be generated",
|
help="which variant of the version string should be generated",
|
||||||
)
|
)
|
||||||
parser.add_argument(
|
parser.add_argument(
|
||||||
"--memgraph-root-dir",
|
"--memgraph-root-dir", help="The root directory of the checked out " "Memgraph repository.", default="."
|
||||||
help="The root directory of the checked out " "Memgraph repository.",
|
|
||||||
default=".",
|
|
||||||
)
|
)
|
||||||
args = parser.parse_args()
|
args = parser.parse_args()
|
||||||
|
|
||||||
@@ -267,27 +256,14 @@ for version in versions:
|
|||||||
if current_version is None:
|
if current_version is None:
|
||||||
raise Exception("You are attempting to determine the version for a very " "old version of Memgraph!")
|
raise Exception("You are attempting to determine the version for a very " "old version of Memgraph!")
|
||||||
version, branch, master_branch_merge = current_version
|
version, branch, master_branch_merge = current_version
|
||||||
distance = int(
|
distance = int(get_output("git", "rev-list", "--count", "--first-parent", master_branch_merge + ".." + current_hash))
|
||||||
get_output(
|
|
||||||
"git",
|
|
||||||
"rev-list",
|
|
||||||
"--count",
|
|
||||||
"--first-parent",
|
|
||||||
master_branch_merge + ".." + current_hash,
|
|
||||||
)
|
|
||||||
)
|
|
||||||
version_str = ".".join(map(str, version)) + ".0"
|
version_str = ".".join(map(str, version)) + ".0"
|
||||||
if distance == 0:
|
if distance == 0:
|
||||||
print(format_version(args.variant, version_str, offering, suffix=args.suffix), end="")
|
print(format_version(args.variant, version_str, offering, suffix=args.suffix), end="")
|
||||||
else:
|
else:
|
||||||
print(
|
print(
|
||||||
format_version(
|
format_version(
|
||||||
args.variant,
|
args.variant, version_str, offering, distance=distance, shorthash=current_hash_short, suffix=args.suffix
|
||||||
version_str,
|
|
||||||
offering,
|
|
||||||
distance=distance,
|
|
||||||
shorthash=current_hash_short,
|
|
||||||
suffix=args.suffix,
|
|
||||||
),
|
),
|
||||||
end="",
|
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
|
# Do NOT be smart here and clean the cache because the container is used in the
|
||||||
# stateful context.
|
# stateful context.
|
||||||
|
|
||||||
RUN wget -q https://s3-eu-west-1.amazonaws.com/deps.memgraph.io/${TOOLCHAIN_VERSION}/${TOOLCHAIN_VERSION}-binaries-centos-7-x86_64.tar.gz \
|
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-x86_64.tar.gz \
|
-O ${TOOLCHAIN_VERSION}-binaries-centos-7.tar.gz \
|
||||||
&& tar xzvf ${TOOLCHAIN_VERSION}-binaries-centos-7-x86_64.tar.gz -C /opt
|
&& tar xzvf ${TOOLCHAIN_VERSION}-binaries-centos-7.tar.gz -C /opt
|
||||||
|
|
||||||
ENTRYPOINT ["sleep", "infinity"]
|
ENTRYPOINT ["sleep", "infinity"]
|
||||||
|
|||||||
14
release/package/centos-8/Dockerfile
Normal file
14
release/package/centos-8/Dockerfile
Normal file
@@ -0,0 +1,14 @@
|
|||||||
|
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"]
|
||||||
@@ -1,14 +0,0 @@
|
|||||||
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
|
# Do NOT be smart here and clean the cache because the container is used in the
|
||||||
# stateful context.
|
# stateful context.
|
||||||
|
|
||||||
RUN wget -q https://s3-eu-west-1.amazonaws.com/deps.memgraph.io/${TOOLCHAIN_VERSION}/${TOOLCHAIN_VERSION}-binaries-debian-10-amd64.tar.gz \
|
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-amd64.tar.gz \
|
-O ${TOOLCHAIN_VERSION}-binaries-debian-10.tar.gz \
|
||||||
&& tar xzvf ${TOOLCHAIN_VERSION}-binaries-debian-10-amd64.tar.gz -C /opt
|
&& tar xzvf ${TOOLCHAIN_VERSION}-binaries-debian-10.tar.gz -C /opt
|
||||||
|
|
||||||
ENTRYPOINT ["sleep", "infinity"]
|
ENTRYPOINT ["sleep", "infinity"]
|
||||||
|
|||||||
@@ -1,17 +0,0 @@
|
|||||||
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
|
# Do NOT be smart here and clean the cache because the container is used in the
|
||||||
# stateful context.
|
# stateful context.
|
||||||
|
|
||||||
RUN wget -q https://s3-eu-west-1.amazonaws.com/deps.memgraph.io/${TOOLCHAIN_VERSION}/${TOOLCHAIN_VERSION}-binaries-debian-11-amd64.tar.gz \
|
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-amd64.tar.gz \
|
-O ${TOOLCHAIN_VERSION}-binaries-debian-11.tar.gz \
|
||||||
&& tar xzvf ${TOOLCHAIN_VERSION}-binaries-debian-11-amd64.tar.gz -C /opt
|
&& tar xzvf ${TOOLCHAIN_VERSION}-binaries-debian-11.tar.gz -C /opt
|
||||||
|
|
||||||
ENTRYPOINT ["sleep", "infinity"]
|
ENTRYPOINT ["sleep", "infinity"]
|
||||||
|
|||||||
@@ -4,10 +4,10 @@ services:
|
|||||||
build:
|
build:
|
||||||
context: centos-7
|
context: centos-7
|
||||||
container_name: "mgbuild_centos-7"
|
container_name: "mgbuild_centos-7"
|
||||||
mgbuild_centos-9:
|
mgbuild_centos-8:
|
||||||
build:
|
build:
|
||||||
context: centos-9
|
context: centos-8
|
||||||
container_name: "mgbuild_centos-9"
|
container_name: "mgbuild_centos-8"
|
||||||
mgbuild_debian-10:
|
mgbuild_debian-10:
|
||||||
build:
|
build:
|
||||||
context: debian-10
|
context: debian-10
|
||||||
@@ -24,7 +24,3 @@ services:
|
|||||||
build:
|
build:
|
||||||
context: ubuntu-20.04
|
context: ubuntu-20.04
|
||||||
container_name: "mgbuild_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
|
set -Eeuo pipefail
|
||||||
|
|
||||||
SCRIPT_DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )"
|
SCRIPT_DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )"
|
||||||
SUPPORTED_OS=(centos-7 centos-9 debian-10 debian-11 ubuntu-18.04 ubuntu-20.04 ubuntu-22.04 debian-11-arm)
|
SUPPORTED_OS=(centos-7 centos-8 debian-10 debian-11 ubuntu-18.04 ubuntu-20.04)
|
||||||
PROJECT_ROOT="$SCRIPT_DIR/../.."
|
PROJECT_ROOT="$SCRIPT_DIR/../.."
|
||||||
TOOLCHAIN_VERSION="toolchain-v4"
|
TOOLCHAIN_VERSION="toolchain-v4"
|
||||||
ACTIVATE_TOOLCHAIN="source /opt/${TOOLCHAIN_VERSION}/activate"
|
ACTIVATE_TOOLCHAIN="source /opt/${TOOLCHAIN_VERSION}/activate"
|
||||||
@@ -67,18 +67,14 @@ make_package () {
|
|||||||
# environment/os/{os}.sh does not come within the toolchain package. When
|
# environment/os/{os}.sh does not come within the toolchain package. When
|
||||||
# migrating to the next version of toolchain do that, and remove the
|
# migrating to the next version of toolchain do that, and remove the
|
||||||
# TOOLCHAIN_RUN_DEPS installation from here.
|
# TOOLCHAIN_RUN_DEPS installation from here.
|
||||||
echo "Installing dependencies using '/memgraph/environment/os/$os.sh' script..."
|
echo "Installing dependencies..."
|
||||||
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 TOOLCHAIN_RUN_DEPS"
|
||||||
docker exec "$build_container" bash -c "/memgraph/environment/os/$os.sh install MEMGRAPH_BUILD_DEPS"
|
docker exec "$build_container" bash -c "/memgraph/environment/os/$os.sh install MEMGRAPH_BUILD_DEPS"
|
||||||
|
|
||||||
echo "Building targeted package..."
|
echo "Building targeted package..."
|
||||||
docker exec "$build_container" bash -c "cd /memgraph && $ACTIVATE_TOOLCHAIN && ./init"
|
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 && rm -rf ./*"
|
||||||
if [[ "$os" == "debian-11-arm" ]]; then
|
docker exec "$build_container" bash -c "cd $container_build_dir && $ACTIVATE_TOOLCHAIN && cmake -DCMAKE_BUILD_TYPE=release $telemetry_id_override_flag .."
|
||||||
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
|
# ' is used instead of " because we need to run make within the allowed
|
||||||
# container resources.
|
# container resources.
|
||||||
# shellcheck disable=SC2016
|
# shellcheck disable=SC2016
|
||||||
|
|||||||
@@ -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
|
# Do NOT be smart here and clean the cache because the container is used in the
|
||||||
# stateful context.
|
# stateful context.
|
||||||
|
|
||||||
RUN wget -q https://s3-eu-west-1.amazonaws.com/deps.memgraph.io/${TOOLCHAIN_VERSION}/${TOOLCHAIN_VERSION}-binaries-ubuntu-18.04-amd64.tar.gz \
|
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-amd64.tar.gz \
|
-O ${TOOLCHAIN_VERSION}-binaries-ubuntu-18.04.tar.gz \
|
||||||
&& tar xzvf ${TOOLCHAIN_VERSION}-binaries-ubuntu-18.04-amd64.tar.gz -C /opt
|
&& tar xzvf ${TOOLCHAIN_VERSION}-binaries-ubuntu-18.04.tar.gz -C /opt
|
||||||
|
|
||||||
ENTRYPOINT ["sleep", "infinity"]
|
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
|
# Do NOT be smart here and clean the cache because the container is used in the
|
||||||
# stateful context.
|
# stateful context.
|
||||||
|
|
||||||
RUN wget -q https://s3-eu-west-1.amazonaws.com/deps.memgraph.io/${TOOLCHAIN_VERSION}/${TOOLCHAIN_VERSION}-binaries-ubuntu-20.04-amd64.tar.gz \
|
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-amd64.tar.gz \
|
-O ${TOOLCHAIN_VERSION}-binaries-ubuntu-20.04.tar.gz \
|
||||||
&& tar xzvf ${TOOLCHAIN_VERSION}-binaries-ubuntu-20.04-amd64.tar.gz -C /opt
|
&& tar xzvf ${TOOLCHAIN_VERSION}-binaries-ubuntu-20.04.tar.gz -C /opt
|
||||||
|
|
||||||
ENTRYPOINT ["sleep", "infinity"]
|
ENTRYPOINT ["sleep", "infinity"]
|
||||||
|
|||||||
@@ -1,17 +0,0 @@
|
|||||||
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 2022 Memgraph Ltd.
|
// Copyright 2021 Memgraph Ltd.
|
||||||
//
|
//
|
||||||
// Licensed as a Memgraph Enterprise file under the Memgraph Enterprise
|
// 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
|
// 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/logging.hpp"
|
||||||
#include "utils/string.hpp"
|
#include "utils/string.hpp"
|
||||||
|
|
||||||
namespace memgraph::audit {
|
namespace audit {
|
||||||
|
|
||||||
// Helper function that converts a `storage::PropertyValue` to `nlohmann::json`.
|
// Helper function that converts a `storage::PropertyValue` to `nlohmann::json`.
|
||||||
inline nlohmann::json PropertyValueToJson(const storage::PropertyValue &pv) {
|
inline nlohmann::json PropertyValueToJson(const storage::PropertyValue &pv) {
|
||||||
@@ -143,4 +143,4 @@ void Log::Flush() {
|
|||||||
log_.Sync();
|
log_.Sync();
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace memgraph::audit
|
} // namespace audit
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
// Copyright 2022 Memgraph Ltd.
|
// Copyright 2021 Memgraph Ltd.
|
||||||
//
|
//
|
||||||
// Licensed as a Memgraph Enterprise file under the Memgraph Enterprise
|
// 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
|
// 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/file.hpp"
|
||||||
#include "utils/scheduler.hpp"
|
#include "utils/scheduler.hpp"
|
||||||
|
|
||||||
namespace memgraph::audit {
|
namespace audit {
|
||||||
|
|
||||||
const uint64_t kBufferSizeDefault = 100000;
|
const uint64_t kBufferSizeDefault = 100000;
|
||||||
const uint64_t kBufferFlushIntervalMillisDefault = 200;
|
const uint64_t kBufferFlushIntervalMillisDefault = 200;
|
||||||
@@ -71,4 +71,4 @@ class Log {
|
|||||||
std::mutex lock_;
|
std::mutex lock_;
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace memgraph::audit
|
} // namespace audit
|
||||||
|
|||||||
@@ -11,7 +11,7 @@ find_package(gflags REQUIRED)
|
|||||||
|
|
||||||
add_library(mg-auth STATIC ${auth_src_files})
|
add_library(mg-auth STATIC ${auth_src_files})
|
||||||
target_link_libraries(mg-auth json libbcrypt gflags fmt::fmt)
|
target_link_libraries(mg-auth json libbcrypt gflags fmt::fmt)
|
||||||
target_link_libraries(mg-auth mg-utils mg-kvstore mg-license )
|
target_link_libraries(mg-auth mg-utils mg-kvstore)
|
||||||
|
|
||||||
target_link_libraries(mg-auth ${Seccomp_LIBRARIES})
|
target_link_libraries(mg-auth ${Seccomp_LIBRARIES})
|
||||||
target_include_directories(mg-auth SYSTEM PRIVATE ${Seccomp_INCLUDE_DIRS})
|
target_include_directories(mg-auth SYSTEM PRIVATE ${Seccomp_INCLUDE_DIRS})
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
// Copyright 2022 Memgraph Ltd.
|
// Copyright 2021 Memgraph Ltd.
|
||||||
//
|
//
|
||||||
// Licensed as a Memgraph Enterprise file under the Memgraph Enterprise
|
// 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
|
// License (the "License"); by using this file, you agree to be bound by the terms of the License, and you may not use
|
||||||
@@ -42,7 +42,8 @@ DEFINE_VALIDATED_int32(auth_module_timeout_ms, 10000,
|
|||||||
"response from the auth module.",
|
"response from the auth module.",
|
||||||
FLAG_IN_RANGE(100, 1800000));
|
FLAG_IN_RANGE(100, 1800000));
|
||||||
|
|
||||||
namespace memgraph::auth {
|
namespace auth {
|
||||||
|
|
||||||
const std::string kUserPrefix = "user:";
|
const std::string kUserPrefix = "user:";
|
||||||
const std::string kRolePrefix = "role:";
|
const std::string kRolePrefix = "role:";
|
||||||
const std::string kLinkPrefix = "link:";
|
const std::string kLinkPrefix = "link:";
|
||||||
@@ -315,4 +316,4 @@ std::vector<auth::User> Auth::AllUsersForRole(const std::string &rolename_orig)
|
|||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace memgraph::auth
|
} // namespace auth
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
// Copyright 2022 Memgraph Ltd.
|
// Copyright 2021 Memgraph Ltd.
|
||||||
//
|
//
|
||||||
// Licensed as a Memgraph Enterprise file under the Memgraph Enterprise
|
// 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
|
// 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,8 @@
|
|||||||
#include "kvstore/kvstore.hpp"
|
#include "kvstore/kvstore.hpp"
|
||||||
#include "utils/settings.hpp"
|
#include "utils/settings.hpp"
|
||||||
|
|
||||||
namespace memgraph::auth {
|
namespace auth {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This class serves as the main Authentication/Authorization storage.
|
* This class serves as the main Authentication/Authorization storage.
|
||||||
* It provides functions for managing Users, Roles and Permissions.
|
* It provides functions for managing Users, Roles and Permissions.
|
||||||
@@ -162,4 +163,4 @@ class Auth final {
|
|||||||
kvstore::KVStore storage_;
|
kvstore::KVStore storage_;
|
||||||
auth::Module module_;
|
auth::Module module_;
|
||||||
};
|
};
|
||||||
} // namespace memgraph::auth
|
} // namespace auth
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
// Copyright 2022 Memgraph Ltd.
|
// Copyright 2021 Memgraph Ltd.
|
||||||
//
|
//
|
||||||
// Licensed as a Memgraph Enterprise file under the Memgraph Enterprise
|
// 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
|
// License (the "License"); by using this file, you agree to be bound by the terms of the License, and you may not use
|
||||||
@@ -12,7 +12,8 @@
|
|||||||
|
|
||||||
#include "auth/exceptions.hpp"
|
#include "auth/exceptions.hpp"
|
||||||
|
|
||||||
namespace memgraph::auth {
|
namespace auth {
|
||||||
|
|
||||||
const std::string EncryptPassword(const std::string &password) {
|
const std::string EncryptPassword(const std::string &password) {
|
||||||
char salt[BCRYPT_HASHSIZE];
|
char salt[BCRYPT_HASHSIZE];
|
||||||
char hash[BCRYPT_HASHSIZE];
|
char hash[BCRYPT_HASHSIZE];
|
||||||
@@ -39,4 +40,4 @@ bool VerifyPassword(const std::string &password, const std::string &hash) {
|
|||||||
return ret == 0;
|
return ret == 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace memgraph::auth
|
} // namespace auth
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
// Copyright 2022 Memgraph Ltd.
|
// Copyright 2021 Memgraph Ltd.
|
||||||
//
|
//
|
||||||
// Licensed as a Memgraph Enterprise file under the Memgraph Enterprise
|
// 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
|
// License (the "License"); by using this file, you agree to be bound by the terms of the License, and you may not use
|
||||||
@@ -10,11 +10,12 @@
|
|||||||
|
|
||||||
#include <string>
|
#include <string>
|
||||||
|
|
||||||
namespace memgraph::auth {
|
namespace auth {
|
||||||
|
|
||||||
/// @throw AuthException if unable to encrypt the password.
|
/// @throw AuthException if unable to encrypt the password.
|
||||||
const std::string EncryptPassword(const std::string &password);
|
const std::string EncryptPassword(const std::string &password);
|
||||||
|
|
||||||
/// @throw AuthException if unable to verify the password.
|
/// @throw AuthException if unable to verify the password.
|
||||||
bool VerifyPassword(const std::string &password, const std::string &hash);
|
bool VerifyPassword(const std::string &password, const std::string &hash);
|
||||||
|
|
||||||
} // namespace memgraph::auth
|
} // namespace auth
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
// Copyright 2022 Memgraph Ltd.
|
// Copyright 2021 Memgraph Ltd.
|
||||||
//
|
//
|
||||||
// Use of this software is governed by the Business Source License
|
// 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
|
// 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,8 @@
|
|||||||
|
|
||||||
#include "utils/exceptions.hpp"
|
#include "utils/exceptions.hpp"
|
||||||
|
|
||||||
namespace memgraph::auth {
|
namespace auth {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This exception class is thrown for all exceptions that can occur when dealing
|
* This exception class is thrown for all exceptions that can occur when dealing
|
||||||
* with the Auth library.
|
* with the Auth library.
|
||||||
@@ -22,4 +23,4 @@ class AuthException : public utils::BasicException {
|
|||||||
public:
|
public:
|
||||||
using utils::BasicException::BasicException;
|
using utils::BasicException::BasicException;
|
||||||
};
|
};
|
||||||
} // namespace memgraph::auth
|
} // namespace auth
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
// Copyright 2022 Memgraph Ltd.
|
// Copyright 2021 Memgraph Ltd.
|
||||||
//
|
//
|
||||||
// Licensed as a Memgraph Enterprise file under the Memgraph Enterprise
|
// 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
|
// License (the "License"); by using this file, you agree to be bound by the terms of the License, and you may not use
|
||||||
@@ -22,23 +22,13 @@
|
|||||||
// NOLINTNEXTLINE(cppcoreguidelines-avoid-non-const-global-variables)
|
// NOLINTNEXTLINE(cppcoreguidelines-avoid-non-const-global-variables)
|
||||||
DEFINE_bool(auth_password_permit_null, true, "Set to false to disable null passwords.");
|
DEFINE_bool(auth_password_permit_null, true, "Set to false to disable null passwords.");
|
||||||
|
|
||||||
inline constexpr std::string_view default_password_regex = ".+";
|
constexpr std::string_view default_password_regex = ".+";
|
||||||
// NOLINTNEXTLINE(cppcoreguidelines-avoid-non-const-global-variables)
|
// NOLINTNEXTLINE(cppcoreguidelines-avoid-non-const-global-variables)
|
||||||
DEFINE_string(auth_password_strength_regex, default_password_regex.data(),
|
DEFINE_string(auth_password_strength_regex, default_password_regex.data(),
|
||||||
"The regular expression that should be used to match the entire "
|
"The regular expression that should be used to match the entire "
|
||||||
"entered password to ensure its strength.");
|
"entered password to ensure its strength.");
|
||||||
|
|
||||||
namespace memgraph::auth {
|
namespace 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) {
|
std::string PermissionToString(Permission permission) {
|
||||||
switch (permission) {
|
switch (permission) {
|
||||||
@@ -78,14 +68,6 @@ std::string PermissionToString(Permission permission) {
|
|||||||
return "AUTH";
|
return "AUTH";
|
||||||
case Permission::STREAM:
|
case Permission::STREAM:
|
||||||
return "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";
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -185,107 +167,19 @@ bool operator==(const Permissions &first, const Permissions &second) {
|
|||||||
|
|
||||||
bool operator!=(const Permissions &first, const Permissions &second) { return !(first == 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) : rolename_(utils::ToLowerCase(rolename)) {}
|
||||||
|
|
||||||
Role::Role(const std::string &rolename, const Permissions &permissions)
|
Role::Role(const std::string &rolename, const Permissions &permissions)
|
||||||
: rolename_(utils::ToLowerCase(rolename)), 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 std::string &Role::rolename() const { return rolename_; }
|
||||||
const Permissions &Role::permissions() const { return permissions_; }
|
const Permissions &Role::permissions() const { return permissions_; }
|
||||||
Permissions &Role::permissions() { return permissions_; }
|
Permissions &Role::permissions() { return permissions_; }
|
||||||
|
|
||||||
LabelPermissions &Role::labelPermissions() { return labelPermissions_; }
|
|
||||||
|
|
||||||
nlohmann::json Role::Serialize() const {
|
nlohmann::json Role::Serialize() const {
|
||||||
nlohmann::json data = nlohmann::json::object();
|
nlohmann::json data = nlohmann::json::object();
|
||||||
data["rolename"] = rolename_;
|
data["rolename"] = rolename_;
|
||||||
data["permissions"] = permissions_.Serialize();
|
data["permissions"] = permissions_.Serialize();
|
||||||
data["labelPermissions"] = labelPermissions_.Serialize();
|
|
||||||
|
|
||||||
return data;
|
return data;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -297,9 +191,7 @@ Role Role::Deserialize(const nlohmann::json &data) {
|
|||||||
throw AuthException("Couldn't load role data!");
|
throw AuthException("Couldn't load role data!");
|
||||||
}
|
}
|
||||||
auto permissions = Permissions::Deserialize(data["permissions"]);
|
auto permissions = Permissions::Deserialize(data["permissions"]);
|
||||||
auto labelPermissions = LabelPermissions::Deserialize(data["labelPermissions"]);
|
return {data["rolename"], permissions};
|
||||||
|
|
||||||
return {data["rolename"], permissions, labelPermissions};
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool operator==(const Role &first, const Role &second) {
|
bool operator==(const Role &first, const Role &second) {
|
||||||
@@ -311,13 +203,6 @@ User::User(const std::string &username) : username_(utils::ToLowerCase(username)
|
|||||||
User::User(const std::string &username, const std::string &password_hash, const Permissions &permissions)
|
User::User(const std::string &username, const std::string &password_hash, const Permissions &permissions)
|
||||||
: username_(utils::ToLowerCase(username)), password_hash_(password_hash), 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) {
|
bool User::CheckPassword(const std::string &password) {
|
||||||
if (password_hash_.empty()) return true;
|
if (password_hash_.empty()) return true;
|
||||||
return VerifyPassword(password, password_hash_);
|
return VerifyPassword(password, password_hash_);
|
||||||
@@ -370,8 +255,6 @@ const std::string &User::username() const { return username_; }
|
|||||||
const Permissions &User::permissions() const { return permissions_; }
|
const Permissions &User::permissions() const { return permissions_; }
|
||||||
Permissions &User::permissions() { return permissions_; }
|
Permissions &User::permissions() { return permissions_; }
|
||||||
|
|
||||||
LabelPermissions &User::labelPermissions() { return labelPermissions_; }
|
|
||||||
|
|
||||||
const Role *User::role() const {
|
const Role *User::role() const {
|
||||||
if (role_.has_value()) {
|
if (role_.has_value()) {
|
||||||
return &role_.value();
|
return &role_.value();
|
||||||
@@ -384,7 +267,6 @@ nlohmann::json User::Serialize() const {
|
|||||||
data["username"] = username_;
|
data["username"] = username_;
|
||||||
data["password_hash"] = password_hash_;
|
data["password_hash"] = password_hash_;
|
||||||
data["permissions"] = permissions_.Serialize();
|
data["permissions"] = permissions_.Serialize();
|
||||||
data["labelPermissions"] = labelPermissions_.Serialize();
|
|
||||||
// The role shouldn't be serialized here, it is stored as a foreign key.
|
// The role shouldn't be serialized here, it is stored as a foreign key.
|
||||||
return data;
|
return data;
|
||||||
}
|
}
|
||||||
@@ -397,14 +279,11 @@ User User::Deserialize(const nlohmann::json &data) {
|
|||||||
throw AuthException("Couldn't load user data!");
|
throw AuthException("Couldn't load user data!");
|
||||||
}
|
}
|
||||||
auto permissions = Permissions::Deserialize(data["permissions"]);
|
auto permissions = Permissions::Deserialize(data["permissions"]);
|
||||||
auto labelPermissions = LabelPermissions::Deserialize(data["labelPermissions"]);
|
return {data["username"], data["password_hash"], permissions};
|
||||||
|
|
||||||
return {data["username"], data["password_hash"], permissions, labelPermissions};
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool operator==(const User &first, const User &second) {
|
bool operator==(const User &first, const User &second) {
|
||||||
return first.username_ == second.username_ && first.password_hash_ == second.password_hash_ &&
|
return first.username_ == second.username_ && first.password_hash_ == second.password_hash_ &&
|
||||||
first.permissions_ == second.permissions_ && first.role_ == second.role_;
|
first.permissions_ == second.permissions_ && first.role_ == second.role_;
|
||||||
}
|
}
|
||||||
|
} // namespace auth
|
||||||
} // namespace memgraph::auth
|
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
// Copyright 2022 Memgraph Ltd.
|
// Copyright 2021 Memgraph Ltd.
|
||||||
//
|
//
|
||||||
// Licensed as a Memgraph Enterprise file under the Memgraph Enterprise
|
// 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
|
// License (the "License"); by using this file, you agree to be bound by the terms of the License, and you may not use
|
||||||
@@ -12,38 +12,42 @@
|
|||||||
#include <string>
|
#include <string>
|
||||||
|
|
||||||
#include <json/json.hpp>
|
#include <json/json.hpp>
|
||||||
#include <unordered_set>
|
|
||||||
|
|
||||||
namespace memgraph::auth {
|
namespace auth {
|
||||||
|
|
||||||
// These permissions must have values that are applicable for usage in a
|
// These permissions must have values that are applicable for usage in a
|
||||||
// bitmask.
|
// bitmask.
|
||||||
// clang-format off
|
// clang-format off
|
||||||
enum class Permission : uint64_t {
|
enum class Permission : uint64_t {
|
||||||
MATCH = 1,
|
MATCH = 1,
|
||||||
CREATE = 1U << 1U,
|
CREATE = 1U << 1U,
|
||||||
MERGE = 1U << 2U,
|
MERGE = 1U << 2U,
|
||||||
DELETE = 1U << 3U,
|
DELETE = 1U << 3U,
|
||||||
SET = 1U << 4U,
|
SET = 1U << 4U,
|
||||||
REMOVE = 1U << 5U,
|
REMOVE = 1U << 5U,
|
||||||
INDEX = 1U << 6U,
|
INDEX = 1U << 6U,
|
||||||
STATS = 1U << 7U,
|
STATS = 1U << 7U,
|
||||||
CONSTRAINT = 1U << 8U,
|
CONSTRAINT = 1U << 8U,
|
||||||
DUMP = 1U << 9U,
|
DUMP = 1U << 9U,
|
||||||
REPLICATION = 1U << 10U,
|
REPLICATION = 1U << 10U,
|
||||||
DURABILITY = 1U << 11U,
|
DURABILITY = 1U << 11U,
|
||||||
READ_FILE = 1U << 12U,
|
READ_FILE = 1U << 12U,
|
||||||
FREE_MEMORY = 1U << 13U,
|
FREE_MEMORY = 1U << 13U,
|
||||||
TRIGGER = 1U << 14U,
|
TRIGGER = 1U << 14U,
|
||||||
CONFIG = 1U << 15U,
|
CONFIG = 1U << 15U,
|
||||||
AUTH = 1U << 16U,
|
AUTH = 1U << 16U,
|
||||||
STREAM = 1U << 17U,
|
STREAM = 1U << 17U
|
||||||
MODULE_READ = 1U << 18U,
|
|
||||||
MODULE_WRITE = 1U << 19U,
|
|
||||||
WEBSOCKET = 1U << 20U,
|
|
||||||
LABELS = 1U << 21U
|
|
||||||
};
|
};
|
||||||
// clang-format on
|
// 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.
|
// Function that converts a permission to its string representation.
|
||||||
std::string PermissionToString(Permission permission);
|
std::string PermissionToString(Permission permission);
|
||||||
|
|
||||||
@@ -90,52 +94,16 @@ bool operator==(const Permissions &first, const Permissions &second);
|
|||||||
|
|
||||||
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 {
|
class Role final {
|
||||||
public:
|
public:
|
||||||
Role(const std::string &rolename);
|
Role(const std::string &rolename);
|
||||||
|
|
||||||
Role(const std::string &rolename, const Permissions &permissions);
|
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 std::string &rolename() const;
|
||||||
const Permissions &permissions() const;
|
const Permissions &permissions() const;
|
||||||
Permissions &permissions();
|
Permissions &permissions();
|
||||||
|
|
||||||
LabelPermissions &labelPermissions();
|
|
||||||
|
|
||||||
nlohmann::json Serialize() const;
|
nlohmann::json Serialize() const;
|
||||||
|
|
||||||
/// @throw AuthException if unable to deserialize.
|
/// @throw AuthException if unable to deserialize.
|
||||||
@@ -146,7 +114,6 @@ class Role final {
|
|||||||
private:
|
private:
|
||||||
std::string rolename_;
|
std::string rolename_;
|
||||||
Permissions permissions_;
|
Permissions permissions_;
|
||||||
LabelPermissions labelPermissions_;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
bool operator==(const Role &first, const Role &second);
|
bool operator==(const Role &first, const Role &second);
|
||||||
@@ -158,9 +125,6 @@ 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);
|
||||||
|
|
||||||
User(const std::string &username, const std::string &password_hash, const Permissions &permissions,
|
|
||||||
const LabelPermissions &labelPermissions);
|
|
||||||
|
|
||||||
/// @throw AuthException if unable to verify the password.
|
/// @throw AuthException if unable to verify the password.
|
||||||
bool CheckPassword(const std::string &password);
|
bool CheckPassword(const std::string &password);
|
||||||
|
|
||||||
@@ -180,8 +144,6 @@ class User final {
|
|||||||
|
|
||||||
const Role *role() const;
|
const Role *role() const;
|
||||||
|
|
||||||
LabelPermissions &labelPermissions();
|
|
||||||
|
|
||||||
nlohmann::json Serialize() const;
|
nlohmann::json Serialize() const;
|
||||||
|
|
||||||
/// @throw AuthException if unable to deserialize.
|
/// @throw AuthException if unable to deserialize.
|
||||||
@@ -194,9 +156,7 @@ class User final {
|
|||||||
std::string password_hash_;
|
std::string password_hash_;
|
||||||
Permissions permissions_;
|
Permissions permissions_;
|
||||||
std::optional<Role> role_;
|
std::optional<Role> role_;
|
||||||
LabelPermissions labelPermissions_;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
bool operator==(const User &first, const User &second);
|
bool operator==(const User &first, const User &second);
|
||||||
|
} // namespace auth
|
||||||
} // namespace memgraph::auth
|
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
// Copyright 2022 Memgraph Ltd.
|
// Copyright 2021 Memgraph Ltd.
|
||||||
//
|
//
|
||||||
// Licensed as a Memgraph Enterprise file under the Memgraph Enterprise
|
// 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
|
// 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.
|
// process and something really bad could happen.
|
||||||
|
|
||||||
// Get a pointer to the passed arguments.
|
// Get a pointer to the passed arguments.
|
||||||
auto *ta = reinterpret_cast<memgraph::auth::TargetArguments *>(arg);
|
auto *ta = reinterpret_cast<auth::TargetArguments *>(arg);
|
||||||
|
|
||||||
// Redirect `stdin` to `/dev/null`.
|
// Redirect `stdin` to `/dev/null`.
|
||||||
int fd = open("/dev/null", O_RDONLY | O_CLOEXEC);
|
int fd = open("/dev/null", O_RDONLY | O_CLOEXEC);
|
||||||
@@ -312,7 +312,8 @@ nlohmann::json GetData(int fd, int timeout_millisec) {
|
|||||||
|
|
||||||
} // namespace
|
} // namespace
|
||||||
|
|
||||||
namespace memgraph::auth {
|
namespace auth {
|
||||||
|
|
||||||
Module::Module(const std::filesystem::path &module_executable_path) {
|
Module::Module(const std::filesystem::path &module_executable_path) {
|
||||||
if (!module_executable_path.empty()) {
|
if (!module_executable_path.empty()) {
|
||||||
module_executable_path_ = std::filesystem::absolute(module_executable_path);
|
module_executable_path_ = std::filesystem::absolute(module_executable_path);
|
||||||
@@ -446,4 +447,4 @@ void Module::Shutdown() {
|
|||||||
|
|
||||||
Module::~Module() { Shutdown(); }
|
Module::~Module() { Shutdown(); }
|
||||||
|
|
||||||
} // namespace memgraph::auth
|
} // namespace auth
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
// Copyright 2022 Memgraph Ltd.
|
// Copyright 2021 Memgraph Ltd.
|
||||||
//
|
//
|
||||||
// Licensed as a Memgraph Enterprise file under the Memgraph Enterprise
|
// 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
|
// License (the "License"); by using this file, you agree to be bound by the terms of the License, and you may not use
|
||||||
@@ -16,7 +16,8 @@
|
|||||||
|
|
||||||
#include <json/json.hpp>
|
#include <json/json.hpp>
|
||||||
|
|
||||||
namespace memgraph::auth {
|
namespace auth {
|
||||||
|
|
||||||
struct TargetArguments {
|
struct TargetArguments {
|
||||||
std::filesystem::path module_executable_path;
|
std::filesystem::path module_executable_path;
|
||||||
int pipe_to_module{-1};
|
int pipe_to_module{-1};
|
||||||
@@ -69,4 +70,4 @@ class Module final {
|
|||||||
int pipe_from_module_[2] = {-1, -1};
|
int pipe_from_module_[2] = {-1, -1};
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace memgraph::auth
|
} // namespace auth
|
||||||
|
|||||||
@@ -18,24 +18,19 @@ roles_config = config["roles"]
|
|||||||
# Initialize LDAP server.
|
# Initialize LDAP server.
|
||||||
tls = None
|
tls = None
|
||||||
if server_config["encryption"] != "disabled":
|
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
|
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
|
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
|
validate = ssl.CERT_REQUIRED if server_config["validate_cert"] \
|
||||||
tls = ldap3.Tls(
|
else ssl.CERT_NONE
|
||||||
local_private_key_file=key_file,
|
tls = ldap3.Tls(local_private_key_file=key_file,
|
||||||
local_certificate_file=cert_file,
|
local_certificate_file=cert_file,
|
||||||
ca_certs_file=ca_file,
|
ca_certs_file=ca_file,
|
||||||
validate=validate,
|
validate=validate)
|
||||||
)
|
|
||||||
use_ssl = server_config["encryption"] == "ssl"
|
use_ssl = server_config["encryption"] == "ssl"
|
||||||
server = ldap3.Server(
|
server = ldap3.Server(server_config["host"], port=server_config["port"],
|
||||||
server_config["host"],
|
tls=tls, use_ssl=use_ssl, get_info=ldap3.ALL)
|
||||||
port=server_config["port"],
|
|
||||||
tls=tls,
|
|
||||||
use_ssl=use_ssl,
|
|
||||||
get_info=ldap3.ALL,
|
|
||||||
)
|
|
||||||
|
|
||||||
|
|
||||||
# Main authentication/authorization function.
|
# Main authentication/authorization function.
|
||||||
@@ -45,12 +40,14 @@ def authenticate(username, password):
|
|||||||
return {"authenticated": False, "role": ""}
|
return {"authenticated": False, "role": ""}
|
||||||
|
|
||||||
# Create the DN of the user
|
# 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
|
# Bind to the server
|
||||||
conn = ldap3.Connection(server, dn, password)
|
conn = ldap3.Connection(server, dn, password)
|
||||||
if server_config["encryption"] == "starttls" and not conn.start_tls():
|
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": ""}
|
return {"authenticated": False, "role": ""}
|
||||||
if not conn.bind():
|
if not conn.bind():
|
||||||
return {"authenticated": False, "role": ""}
|
return {"authenticated": False, "role": ""}
|
||||||
@@ -59,32 +56,25 @@ def authenticate(username, password):
|
|||||||
if roles_config["root_dn"] != "":
|
if roles_config["root_dn"] != "":
|
||||||
# search for role
|
# search for role
|
||||||
search_filter = "(&(objectclass={objclass})({attr}={value}))".format(
|
search_filter = "(&(objectclass={objclass})({attr}={value}))".format(
|
||||||
objclass=roles_config["root_objectclass"],
|
objclass=roles_config["root_objectclass"],
|
||||||
attr=roles_config["user_attribute"],
|
attr=roles_config["user_attribute"],
|
||||||
value=ldap3.utils.conv.escape_filter_chars(dn),
|
value=ldap3.utils.conv.escape_filter_chars(dn))
|
||||||
)
|
succ = conn.search(roles_config["root_dn"], search_filter,
|
||||||
succ = conn.search(
|
search_scope=ldap3.LEVEL,
|
||||||
roles_config["root_dn"],
|
attributes=[roles_config["role_attribute"]])
|
||||||
search_filter,
|
|
||||||
search_scope=ldap3.LEVEL,
|
|
||||||
attributes=[roles_config["role_attribute"]],
|
|
||||||
)
|
|
||||||
if not succ or len(conn.entries) == 0:
|
if not succ or len(conn.entries) == 0:
|
||||||
return {"authenticated": True, "role": ""}
|
return {"authenticated": True, "role": ""}
|
||||||
if len(conn.entries) > 1:
|
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
|
# Because we don't know exactly which role the user should have
|
||||||
# we authorize the user with an empty role.
|
# we authorize the user with an empty role.
|
||||||
print(
|
print("WARNING: Found more than one role for "
|
||||||
"WARNING: Found more than one role for " "user '" + username + "':",
|
"user '" + username + "':", ", ".join(roles) + "!",
|
||||||
", ".join(roles) + "!",
|
file=sys.stderr)
|
||||||
file=sys.stderr,
|
|
||||||
)
|
|
||||||
return {"authenticated": True, "role": ""}
|
return {"authenticated": True, "role": ""}
|
||||||
return {
|
return {"authenticated": True,
|
||||||
"authenticated": True,
|
"role": conn.entries[0][roles_config["role_attribute"]].value}
|
||||||
"role": conn.entries[0][roles_config["role_attribute"]].value,
|
|
||||||
}
|
|
||||||
else:
|
else:
|
||||||
return {"authenticated": True, "role": ""}
|
return {"authenticated": True, "role": ""}
|
||||||
|
|
||||||
|
|||||||
@@ -2,10 +2,6 @@ find_package(fmt REQUIRED)
|
|||||||
find_package(gflags REQUIRED)
|
find_package(gflags REQUIRED)
|
||||||
|
|
||||||
set(communication_src_files
|
set(communication_src_files
|
||||||
websocket/auth.cpp
|
|
||||||
websocket/server.cpp
|
|
||||||
websocket/listener.cpp
|
|
||||||
websocket/session.cpp
|
|
||||||
bolt/v1/value.cpp
|
bolt/v1/value.cpp
|
||||||
buffer.cpp
|
buffer.cpp
|
||||||
client.cpp
|
client.cpp
|
||||||
@@ -13,10 +9,8 @@ set(communication_src_files
|
|||||||
helpers.cpp
|
helpers.cpp
|
||||||
init.cpp)
|
init.cpp)
|
||||||
|
|
||||||
find_package(Boost REQUIRED)
|
|
||||||
|
|
||||||
add_library(mg-communication STATIC ${communication_src_files})
|
add_library(mg-communication STATIC ${communication_src_files})
|
||||||
target_link_libraries(mg-communication Boost::headers Threads::Threads mg-utils mg-io mg-auth fmt::fmt gflags)
|
target_link_libraries(mg-communication Threads::Threads mg-utils mg-io fmt::fmt gflags)
|
||||||
|
|
||||||
find_package(OpenSSL REQUIRED)
|
find_package(OpenSSL REQUIRED)
|
||||||
target_link_libraries(mg-communication ${OPENSSL_LIBRARIES})
|
target_link_libraries(mg-communication ${OPENSSL_LIBRARIES})
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
// Copyright 2022 Memgraph Ltd.
|
// Copyright 2021 Memgraph Ltd.
|
||||||
//
|
//
|
||||||
// Use of this software is governed by the Business Source License
|
// 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
|
// 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/exceptions.hpp"
|
||||||
#include "utils/logging.hpp"
|
#include "utils/logging.hpp"
|
||||||
|
|
||||||
namespace memgraph::communication::bolt {
|
namespace communication::bolt {
|
||||||
|
|
||||||
/// This exception is thrown whenever an error occurs during query execution
|
/// This exception is thrown whenever an error occurs during query execution
|
||||||
/// that isn't fatal (eg. mistyped query or some transient error occurred).
|
/// 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_};
|
ChunkedEncoderBuffer<communication::ClientOutputStream> encoder_buffer_{output_stream_};
|
||||||
ClientEncoder<ChunkedEncoderBuffer<communication::ClientOutputStream>> encoder_{encoder_buffer_};
|
ClientEncoder<ChunkedEncoderBuffer<communication::ClientOutputStream>> encoder_{encoder_buffer_};
|
||||||
};
|
};
|
||||||
} // namespace memgraph::communication::bolt
|
} // namespace communication::bolt
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
// Copyright 2022 Memgraph Ltd.
|
// Copyright 2021 Memgraph Ltd.
|
||||||
//
|
//
|
||||||
// Use of this software is governed by the Business Source License
|
// 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
|
// 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>
|
#include <cstdint>
|
||||||
|
|
||||||
namespace memgraph::communication::bolt {
|
namespace communication::bolt {
|
||||||
|
|
||||||
inline constexpr uint8_t kPreamble[4] = {0x60, 0x60, 0xB0, 0x17};
|
static constexpr uint8_t kPreamble[4] = {0x60, 0x60, 0xB0, 0x17};
|
||||||
inline constexpr uint8_t kProtocol[4] = {0x00, 0x00, 0x00, 0x01};
|
static constexpr uint8_t kProtocol[4] = {0x00, 0x00, 0x00, 0x01};
|
||||||
|
|
||||||
enum class Signature : uint8_t {
|
enum class Signature : uint8_t {
|
||||||
Noop = 0x00,
|
Noop = 0x00,
|
||||||
@@ -95,9 +95,9 @@ enum class Marker : uint8_t {
|
|||||||
Struct16 = 0xDD,
|
Struct16 = 0xDD,
|
||||||
};
|
};
|
||||||
|
|
||||||
inline constexpr uint8_t MarkerString = 0, MarkerList = 1, MarkerMap = 2;
|
static constexpr uint8_t MarkerString = 0, MarkerList = 1, MarkerMap = 2;
|
||||||
inline constexpr Marker MarkerTiny[3] = {Marker::TinyString, Marker::TinyList, Marker::TinyMap};
|
static constexpr Marker MarkerTiny[3] = {Marker::TinyString, Marker::TinyList, Marker::TinyMap};
|
||||||
inline constexpr Marker Marker8[3] = {Marker::String8, Marker::List8, Marker::Map8};
|
static constexpr Marker Marker8[3] = {Marker::String8, Marker::List8, Marker::Map8};
|
||||||
inline constexpr Marker Marker16[3] = {Marker::String16, Marker::List16, Marker::Map16};
|
static constexpr Marker Marker16[3] = {Marker::String16, Marker::List16, Marker::Map16};
|
||||||
inline constexpr Marker Marker32[3] = {Marker::String32, Marker::List32, Marker::Map32};
|
static constexpr Marker Marker32[3] = {Marker::String32, Marker::List32, Marker::Map32};
|
||||||
} // namespace memgraph::communication::bolt
|
} // namespace communication::bolt
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
// Copyright 2022 Memgraph Ltd.
|
// Copyright 2021 Memgraph Ltd.
|
||||||
//
|
//
|
||||||
// Use of this software is governed by the Business Source License
|
// 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
|
// 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 <cstddef>
|
||||||
#include <cstdint>
|
#include <cstdint>
|
||||||
|
|
||||||
namespace memgraph::communication::bolt {
|
namespace communication::bolt {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Sizes related to the chunk defined in Bolt protocol.
|
* Sizes related to the chunk defined in Bolt protocol.
|
||||||
*/
|
*/
|
||||||
inline constexpr size_t kChunkHeaderSize = 2;
|
static constexpr size_t kChunkHeaderSize = 2;
|
||||||
inline constexpr size_t kChunkMaxDataSize = 65535;
|
static constexpr size_t kChunkMaxDataSize = 65535;
|
||||||
inline constexpr size_t kChunkWholeSize = kChunkHeaderSize + kChunkMaxDataSize;
|
static constexpr size_t kChunkWholeSize = kChunkHeaderSize + kChunkMaxDataSize;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Handshake size defined in the Bolt protocol.
|
* Handshake size defined in the Bolt protocol.
|
||||||
*/
|
*/
|
||||||
inline constexpr size_t kHandshakeSize = 20;
|
static constexpr size_t kHandshakeSize = 20;
|
||||||
|
|
||||||
inline constexpr uint16_t kSupportedVersions[] = {0x0100, 0x0400, 0x0401, 0x0403};
|
static constexpr uint16_t kSupportedVersions[] = {0x0100, 0x0400, 0x0401, 0x0403};
|
||||||
|
|
||||||
inline constexpr int kPullAll = -1;
|
static constexpr int kPullAll = -1;
|
||||||
inline constexpr int kPullLast = -1;
|
static constexpr int kPullLast = -1;
|
||||||
} // namespace memgraph::communication::bolt
|
} // namespace communication::bolt
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
// Copyright 2022 Memgraph Ltd.
|
// Copyright 2021 Memgraph Ltd.
|
||||||
//
|
//
|
||||||
// Use of this software is governed by the Business Source License
|
// 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
|
// 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"
|
#include "communication/bolt/v1/constants.hpp"
|
||||||
|
|
||||||
namespace memgraph::communication::bolt {
|
namespace communication::bolt {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This class is used as the return value of the GetChunk function of the
|
* 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_;
|
std::vector<uint8_t> data_;
|
||||||
size_t pos_{0};
|
size_t pos_{0};
|
||||||
};
|
};
|
||||||
} // namespace memgraph::communication::bolt
|
} // namespace communication::bolt
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
// Copyright 2022 Memgraph Ltd.
|
// Copyright 2021 Memgraph Ltd.
|
||||||
//
|
//
|
||||||
// Use of this software is governed by the Business Source License
|
// 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
|
// 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/logging.hpp"
|
||||||
#include "utils/temporal.hpp"
|
#include "utils/temporal.hpp"
|
||||||
|
|
||||||
namespace memgraph::communication::bolt {
|
namespace communication::bolt {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Bolt Decoder.
|
* Bolt Decoder.
|
||||||
@@ -591,4 +591,4 @@ class Decoder {
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
} // namespace memgraph::communication::bolt
|
} // namespace communication::bolt
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
// Copyright 2022 Memgraph Ltd.
|
// Copyright 2021 Memgraph Ltd.
|
||||||
//
|
//
|
||||||
// Use of this software is governed by the Business Source License
|
// 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
|
// 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 "
|
"communication::bolt::Encoder requires uint8_t to be "
|
||||||
"implemented as char or unsigned char.");
|
"implemented as char or unsigned char.");
|
||||||
|
|
||||||
namespace memgraph::communication::bolt {
|
namespace communication::bolt {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Bolt BaseEncoder. Has public interfaces for writing Bolt encoded data.
|
* Bolt BaseEncoder. Has public interfaces for writing Bolt encoded data.
|
||||||
@@ -273,4 +273,4 @@ class BaseEncoder {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace memgraph::communication::bolt
|
} // namespace communication::bolt
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
// Copyright 2022 Memgraph Ltd.
|
// Copyright 2021 Memgraph Ltd.
|
||||||
//
|
//
|
||||||
// Use of this software is governed by the Business Source License
|
// 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
|
// 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"
|
#include "communication/bolt/v1/constants.hpp"
|
||||||
|
|
||||||
namespace memgraph::communication::bolt {
|
namespace communication::bolt {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief ChunkedEncoderBuffer
|
* @brief ChunkedEncoderBuffer
|
||||||
@@ -123,4 +123,4 @@ class ChunkedEncoderBuffer {
|
|||||||
// Amount of data in chunk array.
|
// Amount of data in chunk array.
|
||||||
size_t have_{0};
|
size_t have_{0};
|
||||||
};
|
};
|
||||||
} // namespace memgraph::communication::bolt
|
} // namespace communication::bolt
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
// Copyright 2022 Memgraph Ltd.
|
// Copyright 2021 Memgraph Ltd.
|
||||||
//
|
//
|
||||||
// Use of this software is governed by the Business Source License
|
// 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
|
// 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/codes.hpp"
|
||||||
#include "communication/bolt/v1/encoder/base_encoder.hpp"
|
#include "communication/bolt/v1/encoder/base_encoder.hpp"
|
||||||
|
|
||||||
namespace memgraph::communication::bolt {
|
namespace communication::bolt {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Bolt Client Encoder.
|
* Bolt Client Encoder.
|
||||||
@@ -169,4 +169,4 @@ class ClientEncoder : private BaseEncoder<Buffer> {
|
|||||||
return buffer_.Flush();
|
return buffer_.Flush();
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
} // namespace memgraph::communication::bolt
|
} // namespace communication::bolt
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
// Copyright 2022 Memgraph Ltd.
|
// Copyright 2021 Memgraph Ltd.
|
||||||
//
|
//
|
||||||
// Use of this software is governed by the Business Source License
|
// 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
|
// 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/codes.hpp"
|
||||||
#include "communication/bolt/v1/encoder/base_encoder.hpp"
|
#include "communication/bolt/v1/encoder/base_encoder.hpp"
|
||||||
|
|
||||||
namespace memgraph::communication::bolt {
|
namespace communication::bolt {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Bolt Encoder.
|
* Bolt Encoder.
|
||||||
@@ -158,4 +158,4 @@ class Encoder : private BaseEncoder<Buffer> {
|
|||||||
return buffer_.Flush();
|
return buffer_.Flush();
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
} // namespace memgraph::communication::bolt
|
} // namespace communication::bolt
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
// Copyright 2022 Memgraph Ltd.
|
// Copyright 2021 Memgraph Ltd.
|
||||||
//
|
//
|
||||||
// Use of this software is governed by the Business Source License
|
// 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
|
// 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"
|
#include "utils/exceptions.hpp"
|
||||||
|
|
||||||
namespace memgraph::communication::bolt {
|
namespace communication::bolt {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Used to indicate something is wrong with the client but the transaction is
|
* 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_;
|
std::string code_;
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace memgraph::communication::bolt
|
} // namespace communication::bolt
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
// Copyright 2022 Memgraph Ltd.
|
// Copyright 2021 Memgraph Ltd.
|
||||||
//
|
//
|
||||||
// Use of this software is governed by the Business Source License
|
// 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
|
// 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/exceptions.hpp"
|
||||||
#include "utils/logging.hpp"
|
#include "utils/logging.hpp"
|
||||||
|
|
||||||
namespace memgraph::communication::bolt {
|
namespace communication::bolt {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Bolt Session Exception
|
* Bolt Session Exception
|
||||||
@@ -195,4 +195,4 @@ class Session {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace memgraph::communication::bolt
|
} // namespace communication::bolt
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
// Copyright 2022 Memgraph Ltd.
|
// Copyright 2021 Memgraph Ltd.
|
||||||
//
|
//
|
||||||
// Use of this software is governed by the Business Source License
|
// 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
|
// 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>
|
#include <cstdint>
|
||||||
|
|
||||||
namespace memgraph::communication::bolt {
|
namespace communication::bolt {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This class represents states in execution of the Bolt protocol.
|
* This class represents states in execution of the Bolt protocol.
|
||||||
@@ -55,4 +55,4 @@ enum class State : uint8_t {
|
|||||||
*/
|
*/
|
||||||
Close
|
Close
|
||||||
};
|
};
|
||||||
} // namespace memgraph::communication::bolt
|
} // namespace communication::bolt
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
// Copyright 2022 Memgraph Ltd.
|
// Copyright 2021 Memgraph Ltd.
|
||||||
//
|
//
|
||||||
// Use of this software is governed by the Business Source License
|
// 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
|
// 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/likely.hpp"
|
||||||
#include "utils/logging.hpp"
|
#include "utils/logging.hpp"
|
||||||
|
|
||||||
namespace memgraph::communication::bolt {
|
namespace communication::bolt {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Error state run function
|
* Error state run function
|
||||||
@@ -95,4 +95,4 @@ State StateErrorRun(TSession &session, State state) {
|
|||||||
return state;
|
return state;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} // namespace memgraph::communication::bolt
|
} // namespace communication::bolt
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
// Copyright 2022 Memgraph Ltd.
|
// Copyright 2021 Memgraph Ltd.
|
||||||
//
|
//
|
||||||
// Use of this software is governed by the Business Source License
|
// 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
|
// 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/logging.hpp"
|
||||||
#include "utils/message.hpp"
|
#include "utils/message.hpp"
|
||||||
|
|
||||||
namespace memgraph::communication::bolt {
|
namespace communication::bolt {
|
||||||
|
|
||||||
template <typename TSession>
|
template <typename TSession>
|
||||||
State RunHandlerV1(Signature signature, TSession &session, State state, Marker marker) {
|
State RunHandlerV1(Signature signature, TSession &session, State state, Marker marker) {
|
||||||
@@ -118,4 +118,4 @@ State StateExecutingRun(TSession &session, State state) {
|
|||||||
return State::Close;
|
return State::Close;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} // namespace memgraph::communication::bolt
|
} // namespace communication::bolt
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
// Copyright 2022 Memgraph Ltd.
|
// Copyright 2021 Memgraph Ltd.
|
||||||
//
|
//
|
||||||
// Use of this software is governed by the Business Source License
|
// 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
|
// 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/logging.hpp"
|
||||||
#include "utils/message.hpp"
|
#include "utils/message.hpp"
|
||||||
|
|
||||||
namespace memgraph::communication::bolt {
|
namespace communication::bolt {
|
||||||
// TODO: Revise these error messages
|
// TODO: Revise these error messages
|
||||||
inline std::pair<std::string, std::string> ExceptionToErrorMessage(const std::exception &e) {
|
inline std::pair<std::string, std::string> ExceptionToErrorMessage(const std::exception &e) {
|
||||||
if (const auto *verbose = dynamic_cast<const VerboseError *>(&e)) {
|
if (const auto *verbose = dynamic_cast<const VerboseError *>(&e)) {
|
||||||
@@ -415,4 +415,4 @@ State HandleRoute(TSession &session) {
|
|||||||
}
|
}
|
||||||
return State::Error;
|
return State::Error;
|
||||||
}
|
}
|
||||||
} // namespace memgraph::communication::bolt
|
} // namespace communication::bolt
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
// Copyright 2022 Memgraph Ltd.
|
// Copyright 2021 Memgraph Ltd.
|
||||||
//
|
//
|
||||||
// Use of this software is governed by the Business Source License
|
// 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
|
// 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/likely.hpp"
|
||||||
#include "utils/logging.hpp"
|
#include "utils/logging.hpp"
|
||||||
|
|
||||||
namespace memgraph::communication::bolt {
|
namespace communication::bolt {
|
||||||
|
|
||||||
inline bool CopyProtocolInformationIfSupported(uint16_t version, uint8_t *protocol) {
|
inline bool CopyProtocolInformationIfSupported(uint16_t version, uint8_t *protocol) {
|
||||||
const auto *supported_version = std::find(std::begin(kSupportedVersions), std::end(kSupportedVersions), version);
|
const auto *supported_version = std::find(std::begin(kSupportedVersions), std::end(kSupportedVersions), version);
|
||||||
@@ -110,4 +110,4 @@ State StateHandshakeRun(TSession &session) {
|
|||||||
|
|
||||||
return State::Init;
|
return State::Init;
|
||||||
}
|
}
|
||||||
} // namespace memgraph::communication::bolt
|
} // namespace communication::bolt
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
// Copyright 2022 Memgraph Ltd.
|
// Copyright 2021 Memgraph Ltd.
|
||||||
//
|
//
|
||||||
// Use of this software is governed by the Business Source License
|
// 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
|
// 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/likely.hpp"
|
||||||
#include "utils/logging.hpp"
|
#include "utils/logging.hpp"
|
||||||
|
|
||||||
namespace memgraph::communication::bolt {
|
namespace communication::bolt {
|
||||||
|
|
||||||
namespace details {
|
namespace details {
|
||||||
template <typename TSession>
|
template <typename TSession>
|
||||||
@@ -212,4 +212,4 @@ State StateInitRun(TSession &session) {
|
|||||||
spdlog::trace("Unsupported bolt version:{}.{})!", session.version_.major, session.version_.minor);
|
spdlog::trace("Unsupported bolt version:{}.{})!", session.version_.major, session.version_.minor);
|
||||||
return State::Close;
|
return State::Close;
|
||||||
}
|
}
|
||||||
} // namespace memgraph::communication::bolt
|
} // namespace communication::bolt
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
// Copyright 2022 Memgraph Ltd.
|
// Copyright 2021 Memgraph Ltd.
|
||||||
//
|
//
|
||||||
// Use of this software is governed by the Business Source License
|
// 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
|
// 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/algorithm.hpp"
|
||||||
#include "utils/string.hpp"
|
#include "utils/string.hpp"
|
||||||
|
|
||||||
namespace memgraph::communication::bolt {
|
namespace communication::bolt {
|
||||||
|
|
||||||
#define DEF_GETTER_BY_VAL(type, value_type, field) \
|
#define DEF_GETTER_BY_VAL(type, value_type, field) \
|
||||||
value_type &Value::Value##type() { \
|
value_type &Value::Value##type() { \
|
||||||
@@ -461,4 +461,4 @@ std::ostream &operator<<(std::ostream &os, const Value::Type type) {
|
|||||||
return os << "duration";
|
return os << "duration";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} // namespace memgraph::communication::bolt
|
} // namespace communication::bolt
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
// Copyright 2022 Memgraph Ltd.
|
// Copyright 2021 Memgraph Ltd.
|
||||||
//
|
//
|
||||||
// Use of this software is governed by the Business Source License
|
// 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
|
// 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/exceptions.hpp"
|
||||||
#include "utils/temporal.hpp"
|
#include "utils/temporal.hpp"
|
||||||
|
|
||||||
namespace memgraph::communication::bolt {
|
namespace communication::bolt {
|
||||||
|
|
||||||
/** Forward declaration of Value class. */
|
/** Forward declaration of Value class. */
|
||||||
class Value;
|
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 Path &path);
|
||||||
std::ostream &operator<<(std::ostream &os, const Value &value);
|
std::ostream &operator<<(std::ostream &os, const Value &value);
|
||||||
std::ostream &operator<<(std::ostream &os, const Value::Type type);
|
std::ostream &operator<<(std::ostream &os, const Value::Type type);
|
||||||
} // namespace memgraph::communication::bolt
|
} // namespace communication::bolt
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
// Copyright 2022 Memgraph Ltd.
|
// Copyright 2021 Memgraph Ltd.
|
||||||
//
|
//
|
||||||
// Use of this software is governed by the Business Source License
|
// 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
|
// 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"
|
#include "utils/logging.hpp"
|
||||||
|
|
||||||
namespace memgraph::communication {
|
namespace communication {
|
||||||
|
|
||||||
Buffer::Buffer() : data_(kBufferInitialSize, 0), read_end_(this), write_end_(this) {}
|
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; }
|
void Buffer::Clear() { have_ = 0; }
|
||||||
|
|
||||||
} // namespace memgraph::communication
|
} // namespace communication
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
// Copyright 2022 Memgraph Ltd.
|
// Copyright 2021 Memgraph Ltd.
|
||||||
//
|
//
|
||||||
// Use of this software is governed by the Business Source License
|
// 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
|
// 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"
|
#include "io/network/stream_buffer.hpp"
|
||||||
|
|
||||||
namespace memgraph::communication {
|
namespace communication {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Buffer
|
* @brief Buffer
|
||||||
@@ -171,4 +171,4 @@ class Buffer final {
|
|||||||
ReadEnd read_end_;
|
ReadEnd read_end_;
|
||||||
WriteEnd write_end_;
|
WriteEnd write_end_;
|
||||||
};
|
};
|
||||||
} // namespace memgraph::communication
|
} // namespace communication
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
// Copyright 2022 Memgraph Ltd.
|
// Copyright 2021 Memgraph Ltd.
|
||||||
//
|
//
|
||||||
// Use of this software is governed by the Business Source License
|
// 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
|
// 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 "communication/helpers.hpp"
|
||||||
#include "utils/logging.hpp"
|
#include "utils/logging.hpp"
|
||||||
|
|
||||||
namespace memgraph::communication {
|
namespace communication {
|
||||||
|
|
||||||
Client::Client(ClientContext *context) : context_(context) {}
|
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); }
|
bool ClientOutputStream::Write(const std::string &str, bool have_more) { return client_.Write(str, have_more); }
|
||||||
|
|
||||||
} // namespace memgraph::communication
|
} // namespace communication
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
// Copyright 2022 Memgraph Ltd.
|
// Copyright 2021 Memgraph Ltd.
|
||||||
//
|
//
|
||||||
// Use of this software is governed by the Business Source License
|
// 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
|
// 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/endpoint.hpp"
|
||||||
#include "io/network/socket.hpp"
|
#include "io/network/socket.hpp"
|
||||||
|
|
||||||
namespace memgraph::communication {
|
namespace communication {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This class implements a generic network Client.
|
* This class implements a generic network Client.
|
||||||
* It uses blocking sockets and provides an API that can be used to receive/send
|
* It uses blocking sockets and provides an API that can be used to receive/send
|
||||||
* data over the network connection.
|
* data over the network connection.
|
||||||
*
|
*
|
||||||
* NOTE: If you use this client you **must** create `memgraph::communication::SSLInit`
|
* NOTE: If you use this client you **must** create `communication::SSLInit`
|
||||||
* from the `main` function before using the client!
|
* from the `main` function before using the client!
|
||||||
*/
|
*/
|
||||||
class Client final {
|
class Client final {
|
||||||
@@ -167,4 +167,4 @@ class ClientOutputStream final {
|
|||||||
Client &client_;
|
Client &client_;
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace memgraph::communication
|
} // namespace communication
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
// Copyright 2022 Memgraph Ltd.
|
// Copyright 2021 Memgraph Ltd.
|
||||||
//
|
//
|
||||||
// Use of this software is governed by the Business Source License
|
// 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
|
// included in the file licenses/BSL.txt; by using this file, you agree to be bound by the terms of the Business Source
|
||||||
@@ -10,13 +10,10 @@
|
|||||||
// licenses/APL.txt.
|
// licenses/APL.txt.
|
||||||
|
|
||||||
#include "communication/context.hpp"
|
#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"
|
#include "utils/logging.hpp"
|
||||||
|
|
||||||
namespace memgraph::communication {
|
namespace communication {
|
||||||
|
|
||||||
ClientContext::ClientContext(bool use_ssl) : use_ssl_(use_ssl), ctx_(nullptr) {
|
ClientContext::ClientContext(bool use_ssl) : use_ssl_(use_ssl), ctx_(nullptr) {
|
||||||
if (use_ssl_) {
|
if (use_ssl_) {
|
||||||
@@ -76,66 +73,80 @@ SSL_CTX *ClientContext::context() { return ctx_; }
|
|||||||
|
|
||||||
bool ClientContext::use_ssl() { return use_ssl_; }
|
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,
|
ServerContext::ServerContext(const std::string &key_file, const std::string &cert_file, const std::string &ca_file,
|
||||||
bool verify_peer) {
|
bool verify_peer)
|
||||||
namespace ssl = boost::asio::ssl;
|
: use_ssl_(true),
|
||||||
ctx_.emplace(ssl::context::tls_server);
|
#if OPENSSL_VERSION_NUMBER < 0x10100000L
|
||||||
// NOLINTNEXTLINE(hicpp-signed-bitwise)
|
ctx_(SSL_CTX_new(SSLv23_server_method()))
|
||||||
ctx_->set_options(ssl::context::default_workarounds | ssl::context::no_sslv2 | ssl::context::no_sslv3 |
|
#else
|
||||||
ssl::context::single_dh_use);
|
ctx_(SSL_CTX_new(TLS_server_method()))
|
||||||
ctx_->set_default_verify_paths();
|
#endif
|
||||||
// TODO: add support for encrypted private keys
|
{
|
||||||
// TODO: add certificate revocation list (CRL)
|
// TODO (mferencevic): add support for encrypted private keys
|
||||||
boost::system::error_code ec;
|
// TODO (mferencevic): add certificate revocation list (CRL)
|
||||||
ctx_->use_certificate_chain_file(cert_file, ec);
|
MG_ASSERT(SSL_CTX_use_certificate_file(ctx_, cert_file.c_str(), SSL_FILETYPE_PEM) == 1,
|
||||||
MG_ASSERT(!ec, "Couldn't load server certificate from file: {}", cert_file);
|
"Couldn't load server certificate from file: {}", cert_file);
|
||||||
ctx_->use_private_key_file(key_file, ssl::context::pem, ec);
|
MG_ASSERT(SSL_CTX_use_PrivateKey_file(ctx_, key_file.c_str(), SSL_FILETYPE_PEM) == 1,
|
||||||
MG_ASSERT(!ec, "Couldn't load server private key from file: {}", key_file);
|
"Couldn't load server private key from file: {}", key_file);
|
||||||
|
|
||||||
ctx_->set_options(SSL_OP_NO_SSLv3, ec);
|
// Disable legacy SSL support. Other options can be seen here:
|
||||||
MG_ASSERT(!ec, "Setting options to SSL context failed!");
|
// https://www.openssl.org/docs/man1.0.2/ssl/SSL_CTX_set_options.html
|
||||||
|
SSL_CTX_set_options(ctx_, SSL_OP_NO_SSLv3);
|
||||||
|
|
||||||
if (!ca_file.empty()) {
|
if (ca_file != "") {
|
||||||
// Load the certificate authority file.
|
// Load the certificate authority file.
|
||||||
boost::system::error_code ec;
|
MG_ASSERT(SSL_CTX_load_verify_locations(ctx_, ca_file.c_str(), nullptr) == 1,
|
||||||
ctx_->load_verify_file(ca_file, ec);
|
"Couldn't load certificate authority from file: {}", ca_file);
|
||||||
MG_ASSERT(!ec, "Couldn't load certificate authority from file: {}", ca_file);
|
|
||||||
|
|
||||||
if (verify_peer) {
|
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.
|
// Enable verification of the client certificate.
|
||||||
// NOLINTNEXTLINE(hicpp-signed-bitwise)
|
SSL_CTX_set_verify(ctx_, SSL_VERIFY_PEER | SSL_VERIFY_FAIL_IF_NO_PEER_CERT, nullptr);
|
||||||
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 { std::swap(ctx_, other.ctx_); }
|
ServerContext::ServerContext(ServerContext &&other) noexcept : use_ssl_(other.use_ssl_), ctx_(other.ctx_) {
|
||||||
|
other.use_ssl_ = false;
|
||||||
|
other.ctx_ = nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
ServerContext &ServerContext::operator=(ServerContext &&other) noexcept {
|
ServerContext &ServerContext::operator=(ServerContext &&other) noexcept {
|
||||||
if (this == &other) return *this;
|
if (this == &other) return *this;
|
||||||
|
|
||||||
|
// destroy my objects
|
||||||
|
if (use_ssl_) {
|
||||||
|
SSL_CTX_free(ctx_);
|
||||||
|
}
|
||||||
|
|
||||||
// move other objects to self
|
// move other objects to self
|
||||||
ctx_ = std::move(other.ctx_);
|
use_ssl_ = other.use_ssl_;
|
||||||
|
ctx_ = other.ctx_;
|
||||||
|
|
||||||
// reset other objects
|
// reset other objects
|
||||||
other.ctx_.reset();
|
other.use_ssl_ = false;
|
||||||
|
other.ctx_ = nullptr;
|
||||||
|
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
|
|
||||||
ServerContext::~ServerContext() {}
|
ServerContext::~ServerContext() {
|
||||||
|
if (use_ssl_) {
|
||||||
SSL_CTX *ServerContext::context() {
|
SSL_CTX_free(ctx_);
|
||||||
MG_ASSERT(ctx_);
|
}
|
||||||
return ctx_->native_handle();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
boost::asio::ssl::context &ServerContext::context_clone() {
|
SSL_CTX *ServerContext::context() { return ctx_; }
|
||||||
MG_ASSERT(ctx_);
|
|
||||||
return *ctx_;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool ServerContext::use_ssl() const { return ctx_.has_value(); }
|
bool ServerContext::use_ssl() { return use_ssl_; }
|
||||||
|
|
||||||
} // namespace memgraph::communication
|
} // namespace communication
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
// Copyright 2022 Memgraph Ltd.
|
// Copyright 2021 Memgraph Ltd.
|
||||||
//
|
//
|
||||||
// Use of this software is governed by the Business Source License
|
// 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
|
// included in the file licenses/BSL.txt; by using this file, you agree to be bound by the terms of the Business Source
|
||||||
@@ -11,13 +11,11 @@
|
|||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include <optional>
|
|
||||||
#include <string>
|
#include <string>
|
||||||
|
|
||||||
#include <openssl/ssl.h>
|
#include <openssl/ssl.h>
|
||||||
#include <boost/asio/ssl/context.hpp>
|
|
||||||
|
|
||||||
namespace memgraph::communication {
|
namespace communication {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This class represents a context that should be used with network clients. One
|
* This class represents a context that should be used with network clients. One
|
||||||
@@ -71,7 +69,11 @@ class ClientContext final {
|
|||||||
*/
|
*/
|
||||||
class ServerContext final {
|
class ServerContext final {
|
||||||
public:
|
public:
|
||||||
ServerContext() = default;
|
/**
|
||||||
|
* This constructor constructs a ServerContext that doesn't use SSL.
|
||||||
|
*/
|
||||||
|
ServerContext();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This constructor constructs a ServerContext that uses SSL. The parameters
|
* 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
|
* `key_file` and `cert_file` can't be "" because when setting up a server it
|
||||||
@@ -93,15 +95,16 @@ class ServerContext final {
|
|||||||
ServerContext(ServerContext &&other) noexcept;
|
ServerContext(ServerContext &&other) noexcept;
|
||||||
ServerContext &operator=(ServerContext &&other) noexcept;
|
ServerContext &operator=(ServerContext &&other) noexcept;
|
||||||
|
|
||||||
|
// Destructor that handles ownership of the SSL object.
|
||||||
~ServerContext();
|
~ServerContext();
|
||||||
|
|
||||||
SSL_CTX *context();
|
SSL_CTX *context();
|
||||||
boost::asio::ssl::context &context_clone();
|
|
||||||
|
|
||||||
bool use_ssl() const;
|
bool use_ssl();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
std::optional<boost::asio::ssl::context> ctx_;
|
bool use_ssl_;
|
||||||
|
SSL_CTX *ctx_;
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace memgraph::communication
|
} // namespace communication
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
// Copyright 2022 Memgraph Ltd.
|
// Copyright 2021 Memgraph Ltd.
|
||||||
//
|
//
|
||||||
// Use of this software is governed by the Business Source License
|
// 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
|
// 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"
|
#include "utils/exceptions.hpp"
|
||||||
|
|
||||||
namespace memgraph::communication {
|
namespace communication {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This exception is thrown to indicate to the communication stack that the
|
* This exception is thrown to indicate to the communication stack that the
|
||||||
@@ -22,4 +22,4 @@ namespace memgraph::communication {
|
|||||||
class SessionClosedException : public utils::BasicException {
|
class SessionClosedException : public utils::BasicException {
|
||||||
using utils::BasicException::BasicException;
|
using utils::BasicException::BasicException;
|
||||||
};
|
};
|
||||||
} // namespace memgraph::communication
|
} // namespace communication
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
// Copyright 2022 Memgraph Ltd.
|
// Copyright 2021 Memgraph Ltd.
|
||||||
//
|
//
|
||||||
// Use of this software is governed by the Business Source License
|
// 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
|
// 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"
|
#include "communication/helpers.hpp"
|
||||||
|
|
||||||
namespace memgraph::communication {
|
namespace communication {
|
||||||
|
|
||||||
const std::string SslGetLastError() {
|
const std::string SslGetLastError() {
|
||||||
char buff[2048];
|
char buff[2048];
|
||||||
@@ -21,4 +21,4 @@ const std::string SslGetLastError() {
|
|||||||
ERR_error_string_n(err, buff, sizeof(buff));
|
ERR_error_string_n(err, buff, sizeof(buff));
|
||||||
return std::string(buff);
|
return std::string(buff);
|
||||||
}
|
}
|
||||||
} // namespace memgraph::communication
|
} // namespace communication
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
// Copyright 2022 Memgraph Ltd.
|
// Copyright 2021 Memgraph Ltd.
|
||||||
//
|
//
|
||||||
// Use of this software is governed by the Business Source License
|
// 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
|
// 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>
|
#include <string>
|
||||||
|
|
||||||
namespace memgraph::communication {
|
namespace communication {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This function reads and returns a string describing the last OpenSSL error.
|
* This function reads and returns a string describing the last OpenSSL error.
|
||||||
*/
|
*/
|
||||||
const std::string SslGetLastError();
|
const std::string SslGetLastError();
|
||||||
|
|
||||||
} // namespace memgraph::communication
|
} // namespace communication
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
// Copyright 2022 Memgraph Ltd.
|
// Copyright 2021 Memgraph Ltd.
|
||||||
//
|
//
|
||||||
// Use of this software is governed by the Business Source License
|
// 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
|
// 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/signals.hpp"
|
||||||
#include "utils/spin_lock.hpp"
|
#include "utils/spin_lock.hpp"
|
||||||
|
|
||||||
namespace memgraph::communication {
|
namespace communication {
|
||||||
|
|
||||||
namespace {
|
namespace {
|
||||||
// OpenSSL before 1.1 did not have a out-of-the-box multithreading support
|
// OpenSSL before 1.1 did not have a out-of-the-box multithreading support
|
||||||
@@ -72,4 +72,4 @@ SSLInit::SSLInit() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
SSLInit::~SSLInit() { Cleanup(); }
|
SSLInit::~SSLInit() { Cleanup(); }
|
||||||
} // namespace memgraph::communication
|
} // namespace communication
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
// Copyright 2022 Memgraph Ltd.
|
// Copyright 2021 Memgraph Ltd.
|
||||||
//
|
//
|
||||||
// Use of this software is governed by the Business Source License
|
// 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
|
// 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
|
#pragma once
|
||||||
|
|
||||||
namespace memgraph::communication {
|
namespace communication {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Create this object in each `main` file that uses the Communication stack. It
|
* Create this object in each `main` file that uses the Communication stack. It
|
||||||
@@ -36,4 +36,4 @@ struct SSLInit {
|
|||||||
~SSLInit();
|
~SSLInit();
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace memgraph::communication
|
} // namespace communication
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
// Copyright 2022 Memgraph Ltd.
|
// Copyright 2021 Memgraph Ltd.
|
||||||
//
|
//
|
||||||
// Use of this software is governed by the Business Source License
|
// 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
|
// included in the file licenses/BSL.txt; by using this file, you agree to be bound by the terms of the Business Source
|
||||||
@@ -28,7 +28,7 @@
|
|||||||
#include "utils/spin_lock.hpp"
|
#include "utils/spin_lock.hpp"
|
||||||
#include "utils/thread.hpp"
|
#include "utils/thread.hpp"
|
||||||
|
|
||||||
namespace memgraph::communication {
|
namespace communication {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This class listens to events on an epoll object and processes them.
|
* This class listens to events on an epoll object and processes them.
|
||||||
@@ -273,4 +273,4 @@ class Listener final {
|
|||||||
const std::string service_name_;
|
const std::string service_name_;
|
||||||
const size_t workers_count_;
|
const size_t workers_count_;
|
||||||
};
|
};
|
||||||
} // namespace memgraph::communication
|
} // namespace communication
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
// Copyright 2022 Memgraph Ltd.
|
// Copyright 2021 Memgraph Ltd.
|
||||||
//
|
//
|
||||||
// Use of this software is governed by the Business Source License
|
// 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
|
// included in the file licenses/BSL.txt; by using this file, you agree to be bound by the terms of the Business Source
|
||||||
@@ -29,7 +29,7 @@
|
|||||||
*/
|
*/
|
||||||
class ResultStreamFaker {
|
class ResultStreamFaker {
|
||||||
public:
|
public:
|
||||||
explicit ResultStreamFaker(memgraph::storage::Storage *store) : store_(store) {}
|
explicit ResultStreamFaker(storage::Storage *store) : store_(store) {}
|
||||||
|
|
||||||
ResultStreamFaker(const ResultStreamFaker &) = delete;
|
ResultStreamFaker(const ResultStreamFaker &) = delete;
|
||||||
ResultStreamFaker &operator=(const ResultStreamFaker &) = delete;
|
ResultStreamFaker &operator=(const ResultStreamFaker &) = delete;
|
||||||
@@ -38,25 +38,25 @@ class ResultStreamFaker {
|
|||||||
|
|
||||||
void Header(const std::vector<std::string> &fields) { header_ = fields; }
|
void Header(const std::vector<std::string> &fields) { header_ = fields; }
|
||||||
|
|
||||||
void Result(const std::vector<memgraph::communication::bolt::Value> &values) { results_.push_back(values); }
|
void Result(const std::vector<communication::bolt::Value> &values) { results_.push_back(values); }
|
||||||
|
|
||||||
void Result(const std::vector<memgraph::query::TypedValue> &values) {
|
void Result(const std::vector<query::TypedValue> &values) {
|
||||||
std::vector<memgraph::communication::bolt::Value> bvalues;
|
std::vector<communication::bolt::Value> bvalues;
|
||||||
bvalues.reserve(values.size());
|
bvalues.reserve(values.size());
|
||||||
for (const auto &value : values) {
|
for (const auto &value : values) {
|
||||||
auto maybe_value = memgraph::glue::ToBoltValue(value, *store_, memgraph::storage::View::NEW);
|
auto maybe_value = glue::ToBoltValue(value, *store_, storage::View::NEW);
|
||||||
MG_ASSERT(maybe_value.HasValue());
|
MG_ASSERT(maybe_value.HasValue());
|
||||||
bvalues.push_back(std::move(*maybe_value));
|
bvalues.push_back(std::move(*maybe_value));
|
||||||
}
|
}
|
||||||
results_.push_back(std::move(bvalues));
|
results_.push_back(std::move(bvalues));
|
||||||
}
|
}
|
||||||
|
|
||||||
void Summary(const std::map<std::string, memgraph::communication::bolt::Value> &summary) { summary_ = summary; }
|
void Summary(const std::map<std::string, communication::bolt::Value> &summary) { summary_ = summary; }
|
||||||
|
|
||||||
void Summary(const std::map<std::string, memgraph::query::TypedValue> &summary) {
|
void Summary(const std::map<std::string, query::TypedValue> &summary) {
|
||||||
std::map<std::string, memgraph::communication::bolt::Value> bsummary;
|
std::map<std::string, communication::bolt::Value> bsummary;
|
||||||
for (const auto &item : summary) {
|
for (const auto &item : summary) {
|
||||||
auto maybe_value = memgraph::glue::ToBoltValue(item.second, *store_, memgraph::storage::View::NEW);
|
auto maybe_value = glue::ToBoltValue(item.second, *store_, storage::View::NEW);
|
||||||
MG_ASSERT(maybe_value.HasValue());
|
MG_ASSERT(maybe_value.HasValue());
|
||||||
bsummary.insert({item.first, std::move(*maybe_value)});
|
bsummary.insert({item.first, std::move(*maybe_value)});
|
||||||
}
|
}
|
||||||
@@ -119,17 +119,17 @@ class ResultStreamFaker {
|
|||||||
|
|
||||||
// output the summary
|
// output the summary
|
||||||
os << "Query summary: {";
|
os << "Query summary: {";
|
||||||
memgraph::utils::PrintIterable(os, results.GetSummary(), ", ",
|
utils::PrintIterable(os, results.GetSummary(), ", ",
|
||||||
[&](auto &stream, const auto &kv) { stream << kv.first << ": " << kv.second; });
|
[&](auto &stream, const auto &kv) { stream << kv.first << ": " << kv.second; });
|
||||||
os << "}" << std::endl;
|
os << "}" << std::endl;
|
||||||
|
|
||||||
return os;
|
return os;
|
||||||
}
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
memgraph::storage::Storage *store_;
|
storage::Storage *store_;
|
||||||
// the data that the record stream can accept
|
// the data that the record stream can accept
|
||||||
std::vector<std::string> header_;
|
std::vector<std::string> header_;
|
||||||
std::vector<std::vector<memgraph::communication::bolt::Value>> results_;
|
std::vector<std::vector<communication::bolt::Value>> results_;
|
||||||
std::map<std::string, memgraph::communication::bolt::Value> summary_;
|
std::map<std::string, communication::bolt::Value> summary_;
|
||||||
};
|
};
|
||||||
|
|||||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user