Compare commits
160 Commits
release/2.
...
memory-com
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
54f4c02948 | ||
|
|
c091bae418 | ||
|
|
58546a9fe1 | ||
|
|
ab56abf4ca | ||
|
|
1bd47318cd | ||
|
|
0403b67073 | ||
|
|
9e4babcdbb | ||
|
|
b094fdbadc | ||
|
|
07dea328d8 | ||
|
|
bd1852f407 | ||
|
|
9c51dbbb01 | ||
|
|
c0d4f5e0bc | ||
|
|
974a6e3027 | ||
|
|
d9464c6ffd | ||
|
|
312d01bd0c | ||
|
|
b6b32bec03 | ||
|
|
93992a275b | ||
|
|
b5413c6f82 | ||
|
|
09fd5939da | ||
|
|
02eab6ab9c | ||
|
|
9661c52179 | ||
|
|
e928eed028 | ||
|
|
eb5167dfef | ||
|
|
b952139973 | ||
|
|
28dbcd1545 | ||
|
|
d516e40841 | ||
|
|
a6ec81b179 | ||
|
|
c526ff2a8f | ||
|
|
5f509532f2 | ||
|
|
4b3ba908c7 | ||
|
|
030b554ffd | ||
|
|
4bc5d749b2 | ||
|
|
a426ef9cc3 | ||
|
|
60e167d676 | ||
|
|
3f8befde79 | ||
|
|
9355e58e73 | ||
|
|
476968e2c8 | ||
|
|
97183fb9da | ||
|
|
adb65b2fff | ||
|
|
3bf2cf65ab | ||
|
|
8f3f693f20 | ||
|
|
2e51e703c3 | ||
|
|
adf7533751 | ||
|
|
509183e985 | ||
|
|
1fe2190747 | ||
|
|
762fe6a65d | ||
|
|
271b1a5ddb | ||
|
|
260660f1dd | ||
|
|
e5350a011c | ||
|
|
7bf827bb1e | ||
|
|
5d13c281fa | ||
|
|
020273f475 | ||
|
|
4a99625287 | ||
|
|
5bbed6ef9a | ||
|
|
f0bac53e7b | ||
|
|
514fed51c4 | ||
|
|
2877c343e8 | ||
|
|
50a1d1abb3 | ||
|
|
e8850549d2 | ||
|
|
fd819cd099 | ||
|
|
60f4ffc6a1 | ||
|
|
bd2ec6374a | ||
|
|
c501f59a09 | ||
|
|
210bea83d4 | ||
|
|
57fe3463f2 | ||
|
|
53fcd8ac4d | ||
|
|
259cba5d43 | ||
|
|
285b409927 | ||
|
|
8ebab84324 | ||
|
|
3fd9ce4a33 | ||
|
|
be4eb95a98 | ||
|
|
903a9f4636 | ||
|
|
18bd02423a | ||
|
|
58c0c4cebb | ||
|
|
110ca3968c | ||
|
|
9072fb7703 | ||
|
|
2b7707a2f1 | ||
|
|
76ca019f31 | ||
|
|
609b9a20f1 | ||
|
|
e489e4f3e7 | ||
|
|
ab4d1efe0b | ||
|
|
036da58d30 | ||
|
|
919f07fae1 | ||
|
|
ca1e98ad94 | ||
|
|
f0aca2d23b | ||
|
|
ec9840fff2 | ||
|
|
992e718a97 | ||
|
|
2ec6b7f40b | ||
|
|
05eca46267 | ||
|
|
fae039c215 | ||
|
|
3b9133fd5a | ||
|
|
9d056e7649 | ||
|
|
aa4f68a37d | ||
|
|
84721f7e0a | ||
|
|
261aa4f49b | ||
|
|
5ce1526995 | ||
|
|
cb843ee664 | ||
|
|
0f1ca745e5 | ||
|
|
3b781bf525 | ||
|
|
d573eda8bb | ||
|
|
00226dee24 | ||
|
|
546bfc0ede | ||
|
|
5b1ba10183 | ||
|
|
b25e9968ee | ||
|
|
bcd23fe3cb | ||
|
|
68e5610566 | ||
|
|
0ea96663ba | ||
|
|
da17fe92d6 | ||
|
|
e73eac77a9 | ||
|
|
d51a61fc5f | ||
|
|
b875649270 | ||
|
|
05cc35bf93 | ||
|
|
63f8298033 | ||
|
|
df95775222 | ||
|
|
eb22edfd35 | ||
|
|
1b85d77e9e | ||
|
|
cf1a86ed13 | ||
|
|
7fb3f62703 | ||
|
|
cb4b71bdbd | ||
|
|
30ec570bb9 | ||
|
|
d917c3f0fd | ||
|
|
d842adbed3 | ||
|
|
cdfcbc106c | ||
|
|
651b6f3a5a | ||
|
|
0d9bd74a8a | ||
|
|
802f8aceda | ||
|
|
7ddce539fa | ||
|
|
c3e4f81026 | ||
|
|
208705f296 | ||
|
|
69634a5354 | ||
|
|
b8f282468d | ||
|
|
ab38161cd2 | ||
|
|
3a5f140c2b | ||
|
|
eead0f79fc | ||
|
|
91017b7f36 | ||
|
|
00f8d54249 | ||
|
|
4fcdd52f88 | ||
|
|
6c947947eb | ||
|
|
64fd281b2e | ||
|
|
97e250129e | ||
|
|
b02b201129 | ||
|
|
2c6a55775d | ||
|
|
940bf6722c | ||
|
|
49b5343238 | ||
|
|
26a0866938 | ||
|
|
6545283dac | ||
|
|
69c735934c | ||
|
|
64e837b355 | ||
|
|
a586f2f98d | ||
|
|
9fc51f74a0 | ||
|
|
128771a6ec | ||
|
|
f5a49ed29f | ||
|
|
398503da7a | ||
|
|
0819b40202 | ||
|
|
029be10f1d | ||
|
|
a9dc344b49 | ||
|
|
8b0dca9eab | ||
|
|
cb813c3070 | ||
|
|
6349fc9501 | ||
|
|
c4167bafdd |
@@ -1,6 +1,7 @@
|
|||||||
---
|
---
|
||||||
|
BasedOnStyle: Google
|
||||||
|
---
|
||||||
Language: Cpp
|
Language: Cpp
|
||||||
BasedOnStyle: Google
|
|
||||||
Standard: "c++20"
|
Standard: "c++20"
|
||||||
UseTab: Never
|
UseTab: Never
|
||||||
DerivePointerAlignment: false
|
DerivePointerAlignment: false
|
||||||
|
|||||||
2
.github/pull_request_template.md
vendored
2
.github/pull_request_template.md
vendored
@@ -10,5 +10,5 @@
|
|||||||
|
|
||||||
|
|
||||||
To keep docs changelog up to date, one more thing to do:
|
To keep docs changelog up to date, one more thing to do:
|
||||||
- [ ] Write a release note here
|
- [ ] Write a release note here, including added/changed clauses
|
||||||
- [ ] Tag someone from docs team in the comments
|
- [ ] Tag someone from docs team in the comments
|
||||||
|
|||||||
20
.github/workflows/daily_benchmark.yaml
vendored
20
.github/workflows/daily_benchmark.yaml
vendored
@@ -67,7 +67,11 @@ jobs:
|
|||||||
- name: Run mgbench
|
- name: Run mgbench
|
||||||
run: |
|
run: |
|
||||||
cd tests/mgbench
|
cd tests/mgbench
|
||||||
./benchmark.py --num-workers-for-benchmark 12 --export-results benchmark_result.json pokec/medium/*/*
|
./benchmark.py vendor-native --num-workers-for-benchmark 12 --export-results benchmark_pokec.json pokec/medium/*/*
|
||||||
|
|
||||||
|
./benchmark.py vendor-native --num-workers-for-benchmark 1 --export-results benchmark_supernode.json supernode
|
||||||
|
|
||||||
|
./benchmark.py vendor-native --num-workers-for-benchmark 1 --export-results benchmark_high_write_set_property.json high_write_set_property
|
||||||
|
|
||||||
- name: Upload mgbench results
|
- name: Upload mgbench results
|
||||||
run: |
|
run: |
|
||||||
@@ -76,7 +80,19 @@ jobs:
|
|||||||
source ve3/bin/activate
|
source ve3/bin/activate
|
||||||
pip install -r requirements.txt
|
pip install -r requirements.txt
|
||||||
./main.py --benchmark-name "mgbench" \
|
./main.py --benchmark-name "mgbench" \
|
||||||
--benchmark-results-path "../../tests/mgbench/benchmark_result.json" \
|
--benchmark-results-path "../../tests/mgbench/benchmark_pokec.json" \
|
||||||
|
--github-run-id "${{ github.run_id }}" \
|
||||||
|
--github-run-number "${{ github.run_number }}" \
|
||||||
|
--head-branch-name "${{ env.BRANCH_NAME }}"
|
||||||
|
|
||||||
|
./main.py --benchmark-name "supernode" \
|
||||||
|
--benchmark-results-path "../../tests/mgbench/benchmark_supernode.json" \
|
||||||
|
--github-run-id "${{ github.run_id }}" \
|
||||||
|
--github-run-number "${{ github.run_number }}" \
|
||||||
|
--head-branch-name "${{ env.BRANCH_NAME }}"
|
||||||
|
|
||||||
|
./main.py --benchmark-name "high_write_set_property" \
|
||||||
|
--benchmark-results-path "../../tests/mgbench/benchmark_high_write_set_property.json" \
|
||||||
--github-run-id "${{ github.run_id }}" \
|
--github-run-id "${{ github.run_id }}" \
|
||||||
--github-run-number "${{ github.run_number }}" \
|
--github-run-number "${{ github.run_number }}" \
|
||||||
--head-branch-name "${{ env.BRANCH_NAME }}"
|
--head-branch-name "${{ env.BRANCH_NAME }}"
|
||||||
|
|||||||
35
.github/workflows/diff.yaml
vendored
35
.github/workflows/diff.yaml
vendored
@@ -101,7 +101,7 @@ jobs:
|
|||||||
echo ${file}
|
echo ${file}
|
||||||
if [[ ${file} == *.py ]]; then
|
if [[ ${file} == *.py ]]; then
|
||||||
python3 -m black --check --diff ${file}
|
python3 -m black --check --diff ${file}
|
||||||
python3 -m isort --check-only --diff ${file}
|
python3 -m isort --profile black --check-only --diff ${file}
|
||||||
fi
|
fi
|
||||||
done
|
done
|
||||||
|
|
||||||
@@ -196,22 +196,7 @@ jobs:
|
|||||||
|
|
||||||
- name: Run integration tests
|
- name: Run integration tests
|
||||||
run: |
|
run: |
|
||||||
cd tests/integration
|
tests/integration/run.sh
|
||||||
for name in *; do
|
|
||||||
if [ ! -d $name ]; then continue; fi
|
|
||||||
pushd $name >/dev/null
|
|
||||||
echo "Running: $name"
|
|
||||||
if [ -x prepare.sh ]; then
|
|
||||||
./prepare.sh
|
|
||||||
fi
|
|
||||||
if [ -x runner.py ]; then
|
|
||||||
./runner.py
|
|
||||||
elif [ -x runner.sh ]; then
|
|
||||||
./runner.sh
|
|
||||||
fi
|
|
||||||
echo
|
|
||||||
popd >/dev/null
|
|
||||||
done
|
|
||||||
|
|
||||||
- name: Run cppcheck and clang-format
|
- name: Run cppcheck and clang-format
|
||||||
run: |
|
run: |
|
||||||
@@ -281,21 +266,22 @@ jobs:
|
|||||||
|
|
||||||
- name: Run e2e tests
|
- name: Run e2e tests
|
||||||
run: |
|
run: |
|
||||||
# TODO(gitbuda): Setup mgclient and pymgclient properly.
|
|
||||||
cd tests
|
cd tests
|
||||||
./setup.sh
|
./setup.sh /opt/toolchain-v4/activate
|
||||||
source ve3/bin/activate
|
source ve3/bin/activate_e2e
|
||||||
cd e2e
|
cd e2e
|
||||||
LD_LIBRARY_PATH=$LD_LIBRARY_PATH:../../libs/mgclient/lib python runner.py --workloads-root-directory .
|
./run.sh
|
||||||
|
|
||||||
- name: Run stress test (plain)
|
- name: Run stress test (plain)
|
||||||
run: |
|
run: |
|
||||||
cd tests/stress
|
cd tests/stress
|
||||||
|
source ve3/bin/activate
|
||||||
./continuous_integration
|
./continuous_integration
|
||||||
|
|
||||||
- name: Run stress test (SSL)
|
- name: Run stress test (SSL)
|
||||||
run: |
|
run: |
|
||||||
cd tests/stress
|
cd tests/stress
|
||||||
|
source ve3/bin/activate
|
||||||
./continuous_integration --use-ssl
|
./continuous_integration --use-ssl
|
||||||
|
|
||||||
- name: Run durability test
|
- name: Run durability test
|
||||||
@@ -308,7 +294,6 @@ jobs:
|
|||||||
run: |
|
run: |
|
||||||
# Activate toolchain.
|
# Activate toolchain.
|
||||||
source /opt/toolchain-v4/activate
|
source /opt/toolchain-v4/activate
|
||||||
|
|
||||||
cd build
|
cd build
|
||||||
|
|
||||||
# create mgconsole
|
# create mgconsole
|
||||||
@@ -355,10 +340,8 @@ jobs:
|
|||||||
run: |
|
run: |
|
||||||
# Activate toolchain.
|
# Activate toolchain.
|
||||||
source /opt/toolchain-v4/activate
|
source /opt/toolchain-v4/activate
|
||||||
|
|
||||||
# Initialize dependencies.
|
# Initialize dependencies.
|
||||||
./init
|
./init
|
||||||
|
|
||||||
# Build only memgraph release binarie.
|
# Build only memgraph release binarie.
|
||||||
cd build
|
cd build
|
||||||
cmake -DCMAKE_BUILD_TYPE=release ..
|
cmake -DCMAKE_BUILD_TYPE=release ..
|
||||||
@@ -367,7 +350,7 @@ jobs:
|
|||||||
- name: Run Jepsen tests
|
- name: Run Jepsen tests
|
||||||
run: |
|
run: |
|
||||||
cd tests/jepsen
|
cd tests/jepsen
|
||||||
./run.sh test --binary ../../build/memgraph --run-args "test-all --node-configs resources/node-config.edn" --ignore-run-stdout-logs --ignore-run-stderr-logs
|
./run.sh test-all-individually --binary ../../build/memgraph --ignore-run-stdout-logs --ignore-run-stderr-logs
|
||||||
|
|
||||||
- name: Save Jepsen report
|
- name: Save Jepsen report
|
||||||
uses: actions/upload-artifact@v3
|
uses: actions/upload-artifact@v3
|
||||||
@@ -437,7 +420,7 @@ jobs:
|
|||||||
- name: Run mgbench
|
- name: Run mgbench
|
||||||
run: |
|
run: |
|
||||||
cd tests/mgbench
|
cd tests/mgbench
|
||||||
./benchmark.py --num-workers-for-benchmark 12 --export-results benchmark_result.json pokec/medium/*/*
|
./benchmark.py vendor-native --num-workers-for-benchmark 12 --export-results benchmark_result.json pokec/medium/*/*
|
||||||
|
|
||||||
- name: Upload mgbench results
|
- name: Upload mgbench results
|
||||||
run: |
|
run: |
|
||||||
|
|||||||
60
.github/workflows/package_all.yaml
vendored
60
.github/workflows/package_all.yaml
vendored
@@ -2,7 +2,12 @@ name: Package All
|
|||||||
|
|
||||||
# TODO(gitbuda): Cleanup docker container if GHA job was canceled.
|
# TODO(gitbuda): Cleanup docker container if GHA job was canceled.
|
||||||
|
|
||||||
on: workflow_dispatch
|
on:
|
||||||
|
workflow_dispatch:
|
||||||
|
inputs:
|
||||||
|
memgraph_version:
|
||||||
|
description: "Memgraph version to upload as. If empty upload is skipped. Format: 'X.Y.Z'"
|
||||||
|
required: false
|
||||||
|
|
||||||
jobs:
|
jobs:
|
||||||
centos-7:
|
centos-7:
|
||||||
@@ -106,7 +111,7 @@ jobs:
|
|||||||
- name: "Upload package"
|
- name: "Upload package"
|
||||||
uses: actions/upload-artifact@v3
|
uses: actions/upload-artifact@v3
|
||||||
with:
|
with:
|
||||||
name: ubuntu-1804
|
name: ubuntu-18.04
|
||||||
path: build/output/ubuntu-18.04/memgraph*.deb
|
path: build/output/ubuntu-18.04/memgraph*.deb
|
||||||
|
|
||||||
ubuntu-2004:
|
ubuntu-2004:
|
||||||
@@ -123,7 +128,7 @@ jobs:
|
|||||||
- name: "Upload package"
|
- name: "Upload package"
|
||||||
uses: actions/upload-artifact@v3
|
uses: actions/upload-artifact@v3
|
||||||
with:
|
with:
|
||||||
name: ubuntu-2004
|
name: ubuntu-20.04
|
||||||
path: build/output/ubuntu-20.04/memgraph*.deb
|
path: build/output/ubuntu-20.04/memgraph*.deb
|
||||||
|
|
||||||
ubuntu-2204:
|
ubuntu-2204:
|
||||||
@@ -140,7 +145,7 @@ jobs:
|
|||||||
- name: "Upload package"
|
- name: "Upload package"
|
||||||
uses: actions/upload-artifact@v3
|
uses: actions/upload-artifact@v3
|
||||||
with:
|
with:
|
||||||
name: ubuntu-2204
|
name: ubuntu-22.04
|
||||||
path: build/output/ubuntu-22.04/memgraph*.deb
|
path: build/output/ubuntu-22.04/memgraph*.deb
|
||||||
|
|
||||||
debian-11-platform:
|
debian-11-platform:
|
||||||
@@ -177,9 +182,26 @@ jobs:
|
|||||||
name: fedora-36
|
name: fedora-36
|
||||||
path: build/output/fedora-36/memgraph*.rpm
|
path: build/output/fedora-36/memgraph*.rpm
|
||||||
|
|
||||||
|
amzn-2:
|
||||||
|
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 amzn-2
|
||||||
|
- name: "Upload package"
|
||||||
|
uses: actions/upload-artifact@v3
|
||||||
|
with:
|
||||||
|
name: amzn-2
|
||||||
|
path: build/output/amzn-2/memgraph*.rpm
|
||||||
|
|
||||||
debian-11-arm:
|
debian-11-arm:
|
||||||
runs-on: [self-hosted, DockerMgBuild, ARM64, strange]
|
runs-on: [self-hosted, DockerMgBuild, ARM64, strange]
|
||||||
timeout-minutes: 60
|
timeout-minutes: 120
|
||||||
steps:
|
steps:
|
||||||
- name: "Set up repository"
|
- name: "Set up repository"
|
||||||
uses: actions/checkout@v3
|
uses: actions/checkout@v3
|
||||||
@@ -191,12 +213,12 @@ jobs:
|
|||||||
- name: "Upload package"
|
- name: "Upload package"
|
||||||
uses: actions/upload-artifact@v3
|
uses: actions/upload-artifact@v3
|
||||||
with:
|
with:
|
||||||
name: debian-11-arm
|
name: debian-11-aarch64
|
||||||
path: build/output/debian-11-arm/memgraph*.deb
|
path: build/output/debian-11-arm/memgraph*.deb
|
||||||
|
|
||||||
ubuntu-2204-arm:
|
ubuntu-2204-arm:
|
||||||
runs-on: [self-hosted, DockerMgBuild, ARM64, strange]
|
runs-on: [self-hosted, DockerMgBuild, ARM64, strange]
|
||||||
timeout-minutes: 60
|
timeout-minutes: 120
|
||||||
steps:
|
steps:
|
||||||
- name: "Set up repository"
|
- name: "Set up repository"
|
||||||
uses: actions/checkout@v3
|
uses: actions/checkout@v3
|
||||||
@@ -208,5 +230,27 @@ jobs:
|
|||||||
- name: "Upload package"
|
- name: "Upload package"
|
||||||
uses: actions/upload-artifact@v3
|
uses: actions/upload-artifact@v3
|
||||||
with:
|
with:
|
||||||
name: ubuntu-22.04-arm
|
name: ubuntu-22.04-aarch64
|
||||||
path: build/output/ubuntu-22.04-arm/memgraph*.deb
|
path: build/output/ubuntu-22.04-arm/memgraph*.deb
|
||||||
|
|
||||||
|
upload-to-s3:
|
||||||
|
# only run upload if we specified version. Allows for runs without upload
|
||||||
|
if: "${{ github.event.inputs.memgraph_version != '' }}"
|
||||||
|
needs: [centos-7, centos-9, debian-10, debian-11, docker, ubuntu-1804, ubuntu-2004, ubuntu-2204, debian-11-platform, fedora-36, amzn-2, debian-11-arm, ubuntu-2204-arm]
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
steps:
|
||||||
|
- name: Download artifacts
|
||||||
|
uses: actions/download-artifact@v3
|
||||||
|
with:
|
||||||
|
# name: # if name input parameter is not provided, all artifacts are downloaded
|
||||||
|
# and put in directories named after each one.
|
||||||
|
path: build/output/release
|
||||||
|
- name: Upload to S3
|
||||||
|
uses: jakejarvis/s3-sync-action@v0.5.1
|
||||||
|
env:
|
||||||
|
AWS_S3_BUCKET: "download.memgraph.com"
|
||||||
|
AWS_ACCESS_KEY_ID: ${{ secrets.S3_AWS_ACCESS_KEY_ID }}
|
||||||
|
AWS_SECRET_ACCESS_KEY: ${{ secrets.S3_AWS_SECRET_ACCESS_KEY }}
|
||||||
|
AWS_REGION: "eu-west-1"
|
||||||
|
SOURCE_DIR: "build/output/release"
|
||||||
|
DEST_DIR: "memgraph/v${{ github.event.inputs.memgraph_version }}/"
|
||||||
|
|||||||
24
.github/workflows/release_centos8.yaml
vendored
24
.github/workflows/release_centos8.yaml
vendored
@@ -146,22 +146,7 @@ jobs:
|
|||||||
|
|
||||||
- name: Run integration tests
|
- name: Run integration tests
|
||||||
run: |
|
run: |
|
||||||
cd tests/integration
|
tests/integration/run.sh
|
||||||
for name in *; do
|
|
||||||
if [ ! -d $name ]; then continue; fi
|
|
||||||
pushd $name >/dev/null
|
|
||||||
echo "Running: $name"
|
|
||||||
if [ -x prepare.sh ]; then
|
|
||||||
./prepare.sh
|
|
||||||
fi
|
|
||||||
if [ -x runner.py ]; then
|
|
||||||
./runner.py
|
|
||||||
elif [ -x runner.sh ]; then
|
|
||||||
./runner.sh
|
|
||||||
fi
|
|
||||||
echo
|
|
||||||
popd >/dev/null
|
|
||||||
done
|
|
||||||
|
|
||||||
- name: Run cppcheck and clang-format
|
- name: Run cppcheck and clang-format
|
||||||
run: |
|
run: |
|
||||||
@@ -280,12 +265,11 @@ jobs:
|
|||||||
|
|
||||||
- name: Run e2e tests
|
- name: Run e2e tests
|
||||||
run: |
|
run: |
|
||||||
# TODO(gitbuda): Setup mgclient and pymgclient properly.
|
|
||||||
cd tests
|
cd tests
|
||||||
./setup.sh
|
./setup.sh /opt/toolchain-v4/activate
|
||||||
source ve3/bin/activate
|
source ve3/bin/activate_e2e
|
||||||
cd e2e
|
cd e2e
|
||||||
LD_LIBRARY_PATH=$LD_LIBRARY_PATH:../../libs/mgclient/lib python runner.py --workloads-root-directory .
|
./run.sh
|
||||||
|
|
||||||
- name: Run stress test (plain)
|
- name: Run stress test (plain)
|
||||||
run: |
|
run: |
|
||||||
|
|||||||
28
.github/workflows/release_debian10.yaml
vendored
28
.github/workflows/release_debian10.yaml
vendored
@@ -146,22 +146,7 @@ jobs:
|
|||||||
|
|
||||||
- name: Run integration tests
|
- name: Run integration tests
|
||||||
run: |
|
run: |
|
||||||
cd tests/integration
|
tests/integration/run.sh
|
||||||
for name in *; do
|
|
||||||
if [ ! -d $name ]; then continue; fi
|
|
||||||
pushd $name >/dev/null
|
|
||||||
echo "Running: $name"
|
|
||||||
if [ -x prepare.sh ]; then
|
|
||||||
./prepare.sh
|
|
||||||
fi
|
|
||||||
if [ -x runner.py ]; then
|
|
||||||
./runner.py
|
|
||||||
elif [ -x runner.sh ]; then
|
|
||||||
./runner.sh
|
|
||||||
fi
|
|
||||||
echo
|
|
||||||
popd >/dev/null
|
|
||||||
done
|
|
||||||
|
|
||||||
- name: Run cppcheck and clang-format
|
- name: Run cppcheck and clang-format
|
||||||
run: |
|
run: |
|
||||||
@@ -279,12 +264,11 @@ jobs:
|
|||||||
|
|
||||||
- name: Run e2e tests
|
- name: Run e2e tests
|
||||||
run: |
|
run: |
|
||||||
# TODO(gitbuda): Setup mgclient and pymgclient properly.
|
|
||||||
cd tests
|
cd tests
|
||||||
./setup.sh
|
./setup.sh /opt/toolchain-v4/activate
|
||||||
source ve3/bin/activate
|
source ve3/bin/activate_e2e
|
||||||
cd e2e
|
cd e2e
|
||||||
LD_LIBRARY_PATH=$LD_LIBRARY_PATH:../../libs/mgclient/lib python runner.py --workloads-root-directory .
|
./run.sh
|
||||||
|
|
||||||
- name: Run stress test (plain)
|
- name: Run stress test (plain)
|
||||||
run: |
|
run: |
|
||||||
@@ -334,10 +318,8 @@ jobs:
|
|||||||
run: |
|
run: |
|
||||||
# Activate toolchain.
|
# Activate toolchain.
|
||||||
source /opt/toolchain-v4/activate
|
source /opt/toolchain-v4/activate
|
||||||
|
|
||||||
# Initialize dependencies.
|
# Initialize dependencies.
|
||||||
./init
|
./init
|
||||||
|
|
||||||
# Build only memgraph release binary.
|
# Build only memgraph release binary.
|
||||||
cd build
|
cd build
|
||||||
cmake -DCMAKE_BUILD_TYPE=release ..
|
cmake -DCMAKE_BUILD_TYPE=release ..
|
||||||
@@ -346,7 +328,7 @@ jobs:
|
|||||||
- name: Run Jepsen tests
|
- name: Run Jepsen tests
|
||||||
run: |
|
run: |
|
||||||
cd tests/jepsen
|
cd tests/jepsen
|
||||||
./run.sh test --binary ../../build/memgraph --run-args "test-all --node-configs resources/node-config.edn" --ignore-run-stdout-logs --ignore-run-stderr-logs
|
./run.sh test-all-individually --binary ../../build/memgraph --ignore-run-stdout-logs --ignore-run-stderr-logs
|
||||||
|
|
||||||
- name: Save Jepsen report
|
- name: Save Jepsen report
|
||||||
uses: actions/upload-artifact@v3
|
uses: actions/upload-artifact@v3
|
||||||
|
|||||||
4
.github/workflows/release_docker.yaml
vendored
4
.github/workflows/release_docker.yaml
vendored
@@ -31,8 +31,8 @@ jobs:
|
|||||||
- name: Log in to Docker Hub
|
- name: Log in to Docker Hub
|
||||||
uses: docker/login-action@v2
|
uses: docker/login-action@v2
|
||||||
with:
|
with:
|
||||||
username: ${{ secrets.DOCKER_USERNAME }}
|
username: ${{ secrets.DOCKERHUB_USERNAME }}
|
||||||
password: ${{ secrets.DOCKER_PASSWORD }}
|
password: ${{ secrets.DOCKERHUB_TOKEN }}
|
||||||
|
|
||||||
- name: Download memgraph binary
|
- name: Download memgraph binary
|
||||||
run: |
|
run: |
|
||||||
|
|||||||
63
.github/workflows/release_mgbench_client.yaml
vendored
Normal file
63
.github/workflows/release_mgbench_client.yaml
vendored
Normal file
@@ -0,0 +1,63 @@
|
|||||||
|
name: "Mgbench Bolt Client Publish Docker Image"
|
||||||
|
|
||||||
|
on:
|
||||||
|
workflow_dispatch:
|
||||||
|
inputs:
|
||||||
|
version:
|
||||||
|
description: "Mgbench bolt client version to publish on Dockerhub."
|
||||||
|
required: true
|
||||||
|
force_release:
|
||||||
|
type: boolean
|
||||||
|
required: false
|
||||||
|
default: false
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
mgbench_docker_publish:
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
env:
|
||||||
|
DOCKER_ORGANIZATION_NAME: memgraph
|
||||||
|
DOCKER_REPOSITORY_NAME: mgbench-client
|
||||||
|
|
||||||
|
steps:
|
||||||
|
- name: Checkout
|
||||||
|
uses: actions/checkout@v3
|
||||||
|
|
||||||
|
- name: Set up QEMU
|
||||||
|
uses: docker/setup-qemu-action@v2
|
||||||
|
|
||||||
|
- name: Set up Docker Buildx
|
||||||
|
id: buildx
|
||||||
|
uses: docker/setup-buildx-action@v2
|
||||||
|
|
||||||
|
- name: Log in to Docker Hub
|
||||||
|
uses: docker/login-action@v2
|
||||||
|
with:
|
||||||
|
username: ${{ secrets.DOCKERHUB_USERNAME }}
|
||||||
|
password: ${{ secrets.DOCKERHUB_TOKEN }}
|
||||||
|
|
||||||
|
- name: Check if specified version is already pushed
|
||||||
|
run: |
|
||||||
|
EXISTS=$(docker manifest inspect $DOCKER_ORGANIZATION_NAME/$DOCKER_REPOSITORY_NAME:${{ github.event.inputs.version }} > /dev/null; echo $?)
|
||||||
|
echo $EXISTS
|
||||||
|
if [[ ${EXISTS} -eq 0 ]]; then
|
||||||
|
echo 'The specified version has been already released to DockerHub.'
|
||||||
|
if [[ ${{ github.event.inputs.force_release }} = true ]]; then
|
||||||
|
echo 'Forcing the release!'
|
||||||
|
else
|
||||||
|
echo 'Stopping the release!'
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
else
|
||||||
|
echo 'All good the specified version has not been release to DockerHub.'
|
||||||
|
fi
|
||||||
|
|
||||||
|
- name: Build & push docker images
|
||||||
|
run: |
|
||||||
|
cd tests/mgbench
|
||||||
|
docker buildx build \
|
||||||
|
--build-arg TOOLCHAIN_VERSION=toolchain-v4 \
|
||||||
|
--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 Dockerfile.mgbench_client \
|
||||||
|
--push .
|
||||||
24
.github/workflows/release_ubuntu2004.yaml
vendored
24
.github/workflows/release_ubuntu2004.yaml
vendored
@@ -146,22 +146,7 @@ jobs:
|
|||||||
|
|
||||||
- name: Run integration tests
|
- name: Run integration tests
|
||||||
run: |
|
run: |
|
||||||
cd tests/integration
|
tests/integration/run.sh
|
||||||
for name in *; do
|
|
||||||
if [ ! -d $name ]; then continue; fi
|
|
||||||
pushd $name >/dev/null
|
|
||||||
echo "Running: $name"
|
|
||||||
if [ -x prepare.sh ]; then
|
|
||||||
./prepare.sh
|
|
||||||
fi
|
|
||||||
if [ -x runner.py ]; then
|
|
||||||
./runner.py
|
|
||||||
elif [ -x runner.sh ]; then
|
|
||||||
./runner.sh
|
|
||||||
fi
|
|
||||||
echo
|
|
||||||
popd >/dev/null
|
|
||||||
done
|
|
||||||
|
|
||||||
- name: Run cppcheck and clang-format
|
- name: Run cppcheck and clang-format
|
||||||
run: |
|
run: |
|
||||||
@@ -279,12 +264,11 @@ jobs:
|
|||||||
|
|
||||||
- name: Run e2e tests
|
- name: Run e2e tests
|
||||||
run: |
|
run: |
|
||||||
# TODO(gitbuda): Setup mgclient and pymgclient properly.
|
|
||||||
cd tests
|
cd tests
|
||||||
./setup.sh
|
./setup.sh /opt/toolchain-v4/activate
|
||||||
source ve3/bin/activate
|
source ve3/bin/activate_e2e
|
||||||
cd e2e
|
cd e2e
|
||||||
LD_LIBRARY_PATH=$LD_LIBRARY_PATH:../../libs/mgclient/lib python runner.py --workloads-root-directory .
|
./run.sh
|
||||||
|
|
||||||
- name: Run stress test (plain)
|
- name: Run stress test (plain)
|
||||||
run: |
|
run: |
|
||||||
|
|||||||
32
.github/workflows/upload_to_s3.yaml
vendored
Normal file
32
.github/workflows/upload_to_s3.yaml
vendored
Normal file
@@ -0,0 +1,32 @@
|
|||||||
|
name: Upload Package All artifacts to S3
|
||||||
|
|
||||||
|
on:
|
||||||
|
workflow_dispatch:
|
||||||
|
inputs:
|
||||||
|
memgraph_version:
|
||||||
|
description: "Memgraph version to upload as. Format: 'X.Y.Z'"
|
||||||
|
required: true
|
||||||
|
run_number:
|
||||||
|
description: "# of the package_all workflow run to upload artifacts from. Format: '#XYZ'"
|
||||||
|
required: true
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
upload-to-s3:
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
steps:
|
||||||
|
- name: Download artifacts
|
||||||
|
uses: dawidd6/action-download-artifact@v2
|
||||||
|
with:
|
||||||
|
workflow: package_all.yaml
|
||||||
|
workflow_conclusion: success
|
||||||
|
run_number: "${{ github.event.inputs.run_number }}"
|
||||||
|
path: build/output/release
|
||||||
|
- name: Upload to S3
|
||||||
|
uses: jakejarvis/s3-sync-action@v0.5.1
|
||||||
|
env:
|
||||||
|
AWS_S3_BUCKET: "download.memgraph.com"
|
||||||
|
AWS_ACCESS_KEY_ID: ${{ secrets.S3_AWS_ACCESS_KEY_ID }}
|
||||||
|
AWS_SECRET_ACCESS_KEY: ${{ secrets.S3_AWS_SECRET_ACCESS_KEY }}
|
||||||
|
AWS_REGION: "eu-west-1"
|
||||||
|
SOURCE_DIR: "build/output/release"
|
||||||
|
DEST_DIR: "memgraph/v${{ github.event.inputs.memgraph_version }}/"
|
||||||
9
.gitignore
vendored
9
.gitignore
vendored
@@ -34,9 +34,6 @@ TAGS
|
|||||||
*.fas
|
*.fas
|
||||||
*.fasl
|
*.fasl
|
||||||
|
|
||||||
# LCP generated C++ files
|
|
||||||
*.lcp.cpp
|
|
||||||
|
|
||||||
src/database/distributed/serialization.hpp
|
src/database/distributed/serialization.hpp
|
||||||
src/database/single_node_ha/serialization.hpp
|
src/database/single_node_ha/serialization.hpp
|
||||||
src/distributed/bfs_rpc_messages.hpp
|
src/distributed/bfs_rpc_messages.hpp
|
||||||
@@ -50,15 +47,11 @@ src/distributed/pull_produce_rpc_messages.hpp
|
|||||||
src/distributed/storage_gc_rpc_messages.hpp
|
src/distributed/storage_gc_rpc_messages.hpp
|
||||||
src/distributed/token_sharing_rpc_messages.hpp
|
src/distributed/token_sharing_rpc_messages.hpp
|
||||||
src/distributed/updates_rpc_messages.hpp
|
src/distributed/updates_rpc_messages.hpp
|
||||||
src/query/frontend/ast/ast.hpp
|
|
||||||
src/query/distributed/frontend/ast/ast_serialization.hpp
|
|
||||||
src/durability/distributed/state_delta.hpp
|
src/durability/distributed/state_delta.hpp
|
||||||
src/durability/single_node/state_delta.hpp
|
src/durability/single_node/state_delta.hpp
|
||||||
src/durability/single_node_ha/state_delta.hpp
|
src/durability/single_node_ha/state_delta.hpp
|
||||||
src/query/frontend/semantic/symbol.hpp
|
|
||||||
src/query/distributed/frontend/semantic/symbol_serialization.hpp
|
src/query/distributed/frontend/semantic/symbol_serialization.hpp
|
||||||
src/query/distributed/plan/ops.hpp
|
src/query/distributed/plan/ops.hpp
|
||||||
src/query/plan/operator.hpp
|
|
||||||
src/raft/log_entry.hpp
|
src/raft/log_entry.hpp
|
||||||
src/raft/raft_rpc_messages.hpp
|
src/raft/raft_rpc_messages.hpp
|
||||||
src/raft/snapshot_metadata.hpp
|
src/raft/snapshot_metadata.hpp
|
||||||
@@ -66,3 +59,5 @@ src/raft/storage_info_rpc_messages.hpp
|
|||||||
src/stats/stats_rpc_messages.hpp
|
src/stats/stats_rpc_messages.hpp
|
||||||
src/storage/distributed/rpc/concurrent_id_mapper_rpc_messages.hpp
|
src/storage/distributed/rpc/concurrent_id_mapper_rpc_messages.hpp
|
||||||
src/transactions/distributed/engine_rpc_messages.hpp
|
src/transactions/distributed/engine_rpc_messages.hpp
|
||||||
|
/tests/manual/js/transaction_timeout/package-lock.json
|
||||||
|
/tests/manual/js/transaction_timeout/node_modules/
|
||||||
|
|||||||
@@ -1,20 +1,35 @@
|
|||||||
repos:
|
repos:
|
||||||
- repo: https://github.com/pre-commit/pre-commit-hooks
|
- repo: https://github.com/pre-commit/pre-commit-hooks
|
||||||
rev: v2.3.0
|
rev: v4.4.0
|
||||||
hooks:
|
hooks:
|
||||||
- id: check-yaml
|
- id: check-yaml
|
||||||
|
args: [--allow-multiple-documents]
|
||||||
- id: end-of-file-fixer
|
- id: end-of-file-fixer
|
||||||
- id: trailing-whitespace
|
- id: trailing-whitespace
|
||||||
- repo: https://github.com/psf/black
|
- repo: https://github.com/psf/black
|
||||||
rev: 22.8.0
|
rev: 23.1.0
|
||||||
hooks:
|
hooks:
|
||||||
- id: black
|
- id: black
|
||||||
- repo: https://github.com/pycqa/isort
|
- repo: https://github.com/pycqa/isort
|
||||||
rev: 5.10.1
|
rev: 5.12.0
|
||||||
hooks:
|
hooks:
|
||||||
- id: isort
|
- id: isort
|
||||||
name: isort (python)
|
name: isort (python)
|
||||||
|
args: ["--profile", "black"]
|
||||||
- repo: https://github.com/pre-commit/mirrors-clang-format
|
- repo: https://github.com/pre-commit/mirrors-clang-format
|
||||||
rev: v13.0.0
|
rev: v13.0.0
|
||||||
hooks:
|
hooks:
|
||||||
- id: clang-format
|
- id: clang-format
|
||||||
|
# - repo: local
|
||||||
|
# hooks:
|
||||||
|
# - id: clang-tidy
|
||||||
|
# name: clang-tidy
|
||||||
|
# description: Runs clang-tidy and checks for errors
|
||||||
|
# entry: python ./tools/pre-commit/clang-tidy.py
|
||||||
|
# language: python
|
||||||
|
# files: ^src/
|
||||||
|
# types: [c++, text]
|
||||||
|
# fail_fast: true
|
||||||
|
# require_serial: true
|
||||||
|
# args: [--compile_commands_path=build]
|
||||||
|
# pass_filenames: false
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
# MemGraph CMake configuration
|
# MemGraph CMake configuration
|
||||||
|
|
||||||
cmake_minimum_required(VERSION 3.8)
|
cmake_minimum_required(VERSION 3.12)
|
||||||
|
cmake_policy(SET CMP0076 NEW)
|
||||||
|
|
||||||
# !! IMPORTANT !! run ./project_root/init.sh before cmake command
|
# !! IMPORTANT !! run ./project_root/init.sh before cmake command
|
||||||
# to download dependencies
|
# to download dependencies
|
||||||
@@ -18,10 +19,12 @@ set_directory_properties(PROPERTIES CLEAN_NO_CUSTOM TRUE)
|
|||||||
# during the code coverage process
|
# during the code coverage process
|
||||||
find_program(CCACHE_FOUND ccache)
|
find_program(CCACHE_FOUND ccache)
|
||||||
option(USE_CCACHE "ccache:" ON)
|
option(USE_CCACHE "ccache:" ON)
|
||||||
message(STATUS "CCache: ${USE_CCACHE}")
|
|
||||||
if(CCACHE_FOUND AND USE_CCACHE)
|
if(CCACHE_FOUND AND USE_CCACHE)
|
||||||
set_property(GLOBAL PROPERTY RULE_LAUNCH_COMPILE ccache)
|
set_property(GLOBAL PROPERTY RULE_LAUNCH_COMPILE ccache)
|
||||||
set_property(GLOBAL PROPERTY RULE_LAUNCH_LINK ccache)
|
set_property(GLOBAL PROPERTY RULE_LAUNCH_LINK ccache)
|
||||||
|
message(STATUS "CCache: Used")
|
||||||
|
else ()
|
||||||
|
message(STATUS "CCache: Not used")
|
||||||
endif(CCACHE_FOUND AND USE_CCACHE)
|
endif(CCACHE_FOUND AND USE_CCACHE)
|
||||||
|
|
||||||
# choose a compiler
|
# choose a compiler
|
||||||
@@ -37,7 +40,18 @@ endif()
|
|||||||
|
|
||||||
# -----------------------------------------------------------------------------
|
# -----------------------------------------------------------------------------
|
||||||
|
|
||||||
project(memgraph)
|
project(memgraph LANGUAGES C CXX)
|
||||||
|
|
||||||
|
# NOTE: once in a while this needs to be toggled to check headers are
|
||||||
|
# correct and PCH isn't masking any include issues
|
||||||
|
set(CMAKE_DISABLE_PRECOMPILE_HEADERS OFF)
|
||||||
|
|
||||||
|
#TODO: upgrade to cmake 3.24 + CheckIPOSupported
|
||||||
|
#cmake_policy(SET CMP0138 NEW)
|
||||||
|
#include(CheckIPOSupported)
|
||||||
|
#check_ipo_supported()
|
||||||
|
#set(CMAKE_INTERPROCEDURAL_OPTIMIZATION_Release TRUE)
|
||||||
|
#set(CMAKE_INTERPROCEDURAL_OPTIMIZATION_RelWithDebInfo TRUE)
|
||||||
|
|
||||||
# Install licenses.
|
# Install licenses.
|
||||||
install(DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}/licenses/
|
install(DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}/licenses/
|
||||||
@@ -143,7 +157,9 @@ endif()
|
|||||||
# files used can be seen here:
|
# files used can be seen here:
|
||||||
# https://git-scm.com/book/en/v2/Git-Internals-Git-References
|
# https://git-scm.com/book/en/v2/Git-Internals-Git-References
|
||||||
set(git_directory "${CMAKE_SOURCE_DIR}/.git")
|
set(git_directory "${CMAKE_SOURCE_DIR}/.git")
|
||||||
if (EXISTS "${git_directory}")
|
# Check for directory because if the repo is cloned as a git submodule, .git is
|
||||||
|
# a file and below code doesn't work.
|
||||||
|
if (IS_DIRECTORY "${git_directory}")
|
||||||
set_property(DIRECTORY APPEND PROPERTY
|
set_property(DIRECTORY APPEND PROPERTY
|
||||||
CMAKE_CONFIGURE_DEPENDS "${git_directory}/HEAD")
|
CMAKE_CONFIGURE_DEPENDS "${git_directory}/HEAD")
|
||||||
file(STRINGS "${git_directory}/HEAD" git_head_data)
|
file(STRINGS "${git_directory}/HEAD" git_head_data)
|
||||||
@@ -158,7 +174,7 @@ endif()
|
|||||||
|
|
||||||
# setup CMake module path, defines path for include() and find_package()
|
# setup CMake module path, defines path for include() and find_package()
|
||||||
# https://cmake.org/cmake/help/latest/variable/CMAKE_MODULE_PATH.html
|
# https://cmake.org/cmake/help/latest/variable/CMAKE_MODULE_PATH.html
|
||||||
set(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} ${PROJECT_SOURCE_DIR}/cmake)
|
list(APPEND CMAKE_MODULE_PATH "${CMAKE_CURRENT_SOURCE_DIR}/cmake")
|
||||||
# custom function definitions
|
# custom function definitions
|
||||||
include(functions)
|
include(functions)
|
||||||
# -----------------------------------------------------------------------------
|
# -----------------------------------------------------------------------------
|
||||||
@@ -184,7 +200,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 -Wmissing-field-initializers \
|
||||||
-DBOOST_ASIO_USE_TS_EXECUTOR_AS_DEFAULT")
|
-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.
|
||||||
@@ -199,8 +215,8 @@ set(CMAKE_CXX_FLAGS_RELWITHDEBINFO
|
|||||||
# ** Static linking is allowed only for executables! **
|
# ** Static linking is allowed only for executables! **
|
||||||
set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -static-libgcc -static-libstdc++")
|
set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -static-libgcc -static-libstdc++")
|
||||||
|
|
||||||
# Use gold linker to speedup build
|
# Use lld linker to speedup build
|
||||||
set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -fuse-ld=gold")
|
add_link_options(-fuse-ld=lld) # TODO: use mold linker
|
||||||
|
|
||||||
# release flags
|
# release flags
|
||||||
set(CMAKE_CXX_FLAGS_RELEASE "-O2 -DNDEBUG")
|
set(CMAKE_CXX_FLAGS_RELEASE "-O2 -DNDEBUG")
|
||||||
@@ -231,7 +247,17 @@ endif()
|
|||||||
message(STATUS "CMake build type: ${CMAKE_BUILD_TYPE}")
|
message(STATUS "CMake build type: ${CMAKE_BUILD_TYPE}")
|
||||||
# -----------------------------------------------------------------------------
|
# -----------------------------------------------------------------------------
|
||||||
|
|
||||||
set(MG_ARCH "x86_64" CACHE STRING "Host architecture to build Memgraph on. Supported values are x86_64 (default), ARM64.")
|
add_definitions( -DCMAKE_BUILD_TYPE_NAME="${CMAKE_BUILD_TYPE}")
|
||||||
|
|
||||||
|
if (NOT MG_ARCH)
|
||||||
|
set(MG_ARCH_DESCR "Host architecture to build Memgraph on. Supported values are x86_64, ARM64.")
|
||||||
|
if (${CMAKE_HOST_SYSTEM_PROCESSOR} MATCHES "aarch64")
|
||||||
|
set(MG_ARCH "ARM64" CACHE STRING ${MG_ARCH_DESCR})
|
||||||
|
else()
|
||||||
|
set(MG_ARCH "x86_64" CACHE STRING ${MG_ARCH_DESCR})
|
||||||
|
endif()
|
||||||
|
endif()
|
||||||
|
message(STATUS "MG_ARCH: ${MG_ARCH}")
|
||||||
|
|
||||||
# setup external dependencies -------------------------------------------------
|
# setup external dependencies -------------------------------------------------
|
||||||
|
|
||||||
@@ -276,7 +302,7 @@ set(ENABLE_JEMALLOC ON)
|
|||||||
if (ASAN)
|
if (ASAN)
|
||||||
message(WARNING "Disabling jemalloc as it doesn't work well with ASAN")
|
message(WARNING "Disabling jemalloc as it doesn't work well with ASAN")
|
||||||
set(ENABLE_JEMALLOC OFF)
|
set(ENABLE_JEMALLOC OFF)
|
||||||
# Enable Addres sanitizer and get nicer stack traces in error messages.
|
# Enable Address sanitizer and get nicer stack traces in error messages.
|
||||||
# NOTE: AddressSanitizer uses llvm-symbolizer binary from the Clang
|
# NOTE: AddressSanitizer uses llvm-symbolizer binary from the Clang
|
||||||
# distribution to symbolize the stack traces (note that ideally the
|
# distribution to symbolize the stack traces (note that ideally the
|
||||||
# llvm-symbolizer version must match the version of ASan runtime library).
|
# llvm-symbolizer version must match the version of ASan runtime library).
|
||||||
|
|||||||
@@ -175,7 +175,6 @@ license](./licenses/BSL.txt).</br> Memgraph Enterprise is available under the
|
|||||||
|
|
||||||
- :purple_heart: [**Discord**](https://discord.gg/memgraph)
|
- :purple_heart: [**Discord**](https://discord.gg/memgraph)
|
||||||
- :ocean: [**Stack Overflow**](https://stackoverflow.com/questions/tagged/memgraphdb)
|
- :ocean: [**Stack Overflow**](https://stackoverflow.com/questions/tagged/memgraphdb)
|
||||||
- :busts_in_silhouette: [**Discourse forum**](https://discourse.memgraph.com/)
|
|
||||||
- :bird: [**Twitter**](https://twitter.com/memgraphdb)
|
- :bird: [**Twitter**](https://twitter.com/memgraphdb)
|
||||||
- :movie_camera:
|
- :movie_camera:
|
||||||
[**YouTube**](https://www.youtube.com/channel/UCZ3HOJvHGxtQ_JHxOselBYg)
|
[**YouTube**](https://www.youtube.com/channel/UCZ3HOJvHGxtQ_JHxOselBYg)
|
||||||
|
|||||||
@@ -103,6 +103,10 @@ modifications:
|
|||||||
value: "true"
|
value: "true"
|
||||||
override: false
|
override: false
|
||||||
|
|
||||||
|
- name: "storage_parallel_index_recovery"
|
||||||
|
value: "false"
|
||||||
|
override: true
|
||||||
|
|
||||||
undocumented:
|
undocumented:
|
||||||
- "flag_file"
|
- "flag_file"
|
||||||
- "also_log_to_stderr"
|
- "also_log_to_stderr"
|
||||||
|
|||||||
@@ -23,6 +23,14 @@ def wrap_text(s, initial_indent="# "):
|
|||||||
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")
|
||||||
|
# If something is printed out before the help output, it will break the the
|
||||||
|
# XML parsing -> filter out if something is not XML line because something
|
||||||
|
# can be logged before gflags output (e.g. during the global objects init).
|
||||||
|
# This gets called during memgraph build phase to generate default config
|
||||||
|
# file later installed under /etc/memgraph/memgraph.conf
|
||||||
|
# NOTE: Don't use \n in the gflags description strings.
|
||||||
|
# NOTE: Check here if gflags version changes because of the XML format.
|
||||||
|
data = "\n".join([line for line in data.split("\n") if line.startswith("<")])
|
||||||
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"):
|
||||||
|
|||||||
@@ -202,3 +202,29 @@ for row in csv.reader(stream, delimiter=',', doublequote=True,
|
|||||||
For more information about the meaning of the above values, see:
|
For more information about the meaning of the above values, see:
|
||||||
https://docs.python.org/3/library/csv.html#csv.Dialect
|
https://docs.python.org/3/library/csv.html#csv.Dialect
|
||||||
|
|
||||||
|
## Errors
|
||||||
|
|
||||||
|
1. [Skipping duplicate node with ID '{}'. For more details, visit:
|
||||||
|
memgr.ph/csv-import-tool.](#error-1)
|
||||||
|
2. [Skipping bad relationship with START_ID '{}'. For more details, visit:
|
||||||
|
memgr.ph/csv-import-tool.](#error-2)
|
||||||
|
3. [Skipping bad relationship with END_ID '{}'. For more details, visit:
|
||||||
|
memgr.ph/csv-import-tool.](#error-3)
|
||||||
|
|
||||||
|
## Skipping duplicate node with ID {} {#error-1}
|
||||||
|
|
||||||
|
Duplicate nodes are nodes that have an ID that is the same as another node that
|
||||||
|
was already imported. You can instruct the importer to ignore all duplicate
|
||||||
|
nodes (instead of raising an error) by using the `--skip-duplicate-nodes` flag.
|
||||||
|
|
||||||
|
## Skipping bad relationship with START_ID {} {#error-2}
|
||||||
|
|
||||||
|
A node with the id `START_ID` doesn't exist. You can instruct the importer to
|
||||||
|
ignore all bad relationships (instead of raising an error) that refer to nodes
|
||||||
|
that don't exist in the node files by using the `--skip-bad-relationships` flag.
|
||||||
|
|
||||||
|
## Skipping bad relationship with END_ID {} {#error-3}
|
||||||
|
|
||||||
|
A node with the id `END_ID` doesn't exist. You can instruct the importer to
|
||||||
|
ignore all bad relationships (instead of raising an error) that refer to nodes
|
||||||
|
that don't exist in the node files by using the `--skip-bad-relationships` flag.
|
||||||
|
|||||||
10
environment/README.md
Normal file
10
environment/README.md
Normal file
@@ -0,0 +1,10 @@
|
|||||||
|
# Memgraph Operating Environments
|
||||||
|
|
||||||
|
## os
|
||||||
|
|
||||||
|
Under the `os` directory, you can find scripts to install all required system
|
||||||
|
dependencies on operating systems where Memgraph natively builds. The testing
|
||||||
|
script helps to see how to install all packages (in the case of a new package),
|
||||||
|
or make any adjustments in the overall system setup. Also, the testing script
|
||||||
|
helps check if Memgraph runs on a freshly installed operating system (with no
|
||||||
|
packages installed).
|
||||||
3
environment/os/.gitignore
vendored
3
environment/os/.gitignore
vendored
@@ -1,3 +1,6 @@
|
|||||||
*.deb
|
*.deb
|
||||||
|
*.deb.*
|
||||||
*.rpm
|
*.rpm
|
||||||
|
*.rpm.*
|
||||||
*.tar.gz
|
*.tar.gz
|
||||||
|
*.tar.gz.*
|
||||||
|
|||||||
196
environment/os/amzn-2.sh
Executable file
196
environment/os/amzn-2.sh
Executable file
@@ -0,0 +1,196 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
|
||||||
|
set -Eeuo pipefail
|
||||||
|
|
||||||
|
DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" >/dev/null 2>&1 && pwd )"
|
||||||
|
source "$DIR/../util.sh"
|
||||||
|
|
||||||
|
check_operating_system "amzn-2"
|
||||||
|
check_architecture "x86_64"
|
||||||
|
|
||||||
|
TOOLCHAIN_BUILD_DEPS=(
|
||||||
|
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 xz-devel python3-devel texinfo
|
||||||
|
curl libcurl-devel # for cmake
|
||||||
|
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
|
||||||
|
diffutils
|
||||||
|
patch
|
||||||
|
libipt libipt-devel # intel
|
||||||
|
perl # for openssl
|
||||||
|
)
|
||||||
|
|
||||||
|
TOOLCHAIN_RUN_DEPS=(
|
||||||
|
make # generic build tools
|
||||||
|
tar gzip bzip2 xz # used for archive unpacking
|
||||||
|
zlib # zlib library used for all builds
|
||||||
|
expat xz-libs python3 # for gdb
|
||||||
|
readline # for cmake and llvm
|
||||||
|
libffi libxml2 # for llvm
|
||||||
|
openssl-devel
|
||||||
|
)
|
||||||
|
|
||||||
|
MEMGRAPH_BUILD_DEPS=(
|
||||||
|
git # source code control
|
||||||
|
make cmake # build system
|
||||||
|
wget # for downloading libs
|
||||||
|
libuuid-devel java-11-openjdk # required by antlr
|
||||||
|
readline-devel # for memgraph console
|
||||||
|
python3-devel # for query modules
|
||||||
|
openssl-devel
|
||||||
|
libseccomp-devel
|
||||||
|
python3 python3-pip nmap-ncat # for tests
|
||||||
|
#
|
||||||
|
# IMPORTANT: python3-yaml does NOT exist on CentOS
|
||||||
|
# Install it 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 nodejs golang custom-golang1.18.9 zip unzip java-11-openjdk-devel jdk-17 custom-maven3.9.3 # for driver tests
|
||||||
|
autoconf # for jemalloc code generation
|
||||||
|
libtool # for protobuf code generation
|
||||||
|
cyrus-sasl-devel
|
||||||
|
)
|
||||||
|
|
||||||
|
MEMGRAPH_RUN_DEPS=(
|
||||||
|
logrotate openssl python3 libseccomp
|
||||||
|
)
|
||||||
|
|
||||||
|
NEW_DEPS=(
|
||||||
|
wget curl tar gzip
|
||||||
|
)
|
||||||
|
|
||||||
|
list() {
|
||||||
|
echo "$1"
|
||||||
|
}
|
||||||
|
|
||||||
|
check() {
|
||||||
|
local missing=""
|
||||||
|
# On Fedora yum/dnf and python10 use newer glibc which is not compatible
|
||||||
|
# with ours, so we need to momentarely disable env
|
||||||
|
local OLD_LD_LIBRARY_PATH=${LD_LIBRARY_PATH:-""}
|
||||||
|
LD_LIBRARY_PATH=""
|
||||||
|
for pkg in $1; do
|
||||||
|
if [ "$pkg" == custom-maven3.9.3 ]; then
|
||||||
|
if [ ! -f "/opt/apache-maven-3.9.3/bin/mvn" ]; then
|
||||||
|
missing="$pkg $missing"
|
||||||
|
fi
|
||||||
|
continue
|
||||||
|
fi
|
||||||
|
if [ "$pkg" == custom-golang1.18.9 ]; then
|
||||||
|
if [ ! -f "/opt/go1.18.9/go/bin/go" ]; then
|
||||||
|
missing="$pkg $missing"
|
||||||
|
fi
|
||||||
|
continue
|
||||||
|
fi
|
||||||
|
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
|
||||||
|
LD_LIBRARY_PATH=${OLD_LD_LIBRARY_PATH}
|
||||||
|
}
|
||||||
|
|
||||||
|
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 don't work without 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
|
||||||
|
|
||||||
|
yum update -y
|
||||||
|
for pkg in $1; do
|
||||||
|
if [ "$pkg" == custom-maven3.9.3 ]; then
|
||||||
|
install_custom_maven "3.9.3"
|
||||||
|
continue
|
||||||
|
fi
|
||||||
|
if [ "$pkg" == custom-golang1.18.9 ]; then
|
||||||
|
install_custom_golang "1.18.9"
|
||||||
|
continue
|
||||||
|
fi
|
||||||
|
if [ "$pkg" == jdk-17 ]; then
|
||||||
|
if ! yum list installed jdk-17 >/dev/null 2>/dev/null; then
|
||||||
|
wget --no-check-certificate -c --header "Cookie: oraclelicense=accept-securebackup-cookie" https://download.oracle.com/java/17/latest/jdk-17_linux-x64_bin.rpm
|
||||||
|
rpm -Uvh jdk-17_linux-x64_bin.rpm
|
||||||
|
# NOTE: Set Java 11 as default.
|
||||||
|
update-alternatives --set java java-11-openjdk.x86_64
|
||||||
|
update-alternatives --set javac java-11-openjdk.x86_64
|
||||||
|
fi
|
||||||
|
continue
|
||||||
|
fi
|
||||||
|
if [ "$pkg" == libipt ]; then
|
||||||
|
if ! yum list installed libipt >/dev/null 2>/dev/null; then
|
||||||
|
yum 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
|
||||||
|
yum 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" == nodejs ]; then
|
||||||
|
curl -sL https://rpm.nodesource.com/setup_16.x | bash -
|
||||||
|
if ! yum list installed nodejs >/dev/null 2>/dev/null; then
|
||||||
|
yum install -y nodejs
|
||||||
|
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
|
||||||
|
if [ "$pkg" == nodejs ]; then
|
||||||
|
curl -sL https://rpm.nodesource.com/setup_16.x | bash -
|
||||||
|
if ! yum list installed nodejs >/dev/null 2>/dev/null; then
|
||||||
|
yum install -y nodejs
|
||||||
|
fi
|
||||||
|
continue
|
||||||
|
fi
|
||||||
|
if [ "$pkg" == java-11-openjdk ]; then
|
||||||
|
amazon-linux-extras install -y java-openjdk11
|
||||||
|
continue
|
||||||
|
fi
|
||||||
|
if [ "$pkg" == java-11-openjdk-devel ]; then
|
||||||
|
amazon-linux-extras install -y java-openjdk11
|
||||||
|
yum install -y java-11-openjdk-devel
|
||||||
|
continue
|
||||||
|
fi
|
||||||
|
yum install -y "$pkg"
|
||||||
|
done
|
||||||
|
}
|
||||||
|
|
||||||
|
deps=$2"[*]"
|
||||||
|
"$1" "${!deps}"
|
||||||
@@ -39,7 +39,7 @@ TOOLCHAIN_RUN_DEPS=(
|
|||||||
)
|
)
|
||||||
|
|
||||||
MEMGRAPH_BUILD_DEPS=(
|
MEMGRAPH_BUILD_DEPS=(
|
||||||
make pkgconfig # build system
|
make cmake pkgconfig # build system
|
||||||
curl 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
|
||||||
@@ -56,9 +56,19 @@ MEMGRAPH_BUILD_DEPS=(
|
|||||||
sbcl # for custom Lisp C++ preprocessing
|
sbcl # for custom Lisp C++ preprocessing
|
||||||
rpm-build rpmlint # for RPM package building
|
rpm-build rpmlint # for RPM package building
|
||||||
doxygen graphviz # source documentation generators
|
doxygen graphviz # source documentation generators
|
||||||
which mono-complete dotnet-sdk-3.1 golang nodejs zip unzip java-11-openjdk-devel # for driver tests
|
which mono-complete dotnet-sdk-3.1 golang custom-golang1.18.9 # for driver tests
|
||||||
|
nodejs zip unzip java-11-openjdk-devel jdk-17 custom-maven3.9.3 # for driver tests
|
||||||
autoconf # for jemalloc code generation
|
autoconf # for jemalloc code generation
|
||||||
libtool # for protobuf code generation
|
libtool # for protobuf code generation
|
||||||
|
cyrus-sasl-devel
|
||||||
|
)
|
||||||
|
|
||||||
|
MEMGRAPH_RUN_DEPS=(
|
||||||
|
logrotate openssl python3 libseccomp
|
||||||
|
)
|
||||||
|
|
||||||
|
NEW_DEPS=(
|
||||||
|
wget curl tar gzip
|
||||||
)
|
)
|
||||||
|
|
||||||
list() {
|
list() {
|
||||||
@@ -68,6 +78,18 @@ list() {
|
|||||||
check() {
|
check() {
|
||||||
local missing=""
|
local missing=""
|
||||||
for pkg in $1; do
|
for pkg in $1; do
|
||||||
|
if [ "$pkg" == custom-maven3.9.3 ]; then
|
||||||
|
if [ ! -f "/opt/apache-maven-3.9.3/bin/mvn" ]; then
|
||||||
|
missing="$pkg $missing"
|
||||||
|
fi
|
||||||
|
continue
|
||||||
|
fi
|
||||||
|
if [ "$pkg" == custom-golang1.18.9 ]; then
|
||||||
|
if [ ! -f "/opt/go1.18.9/go/bin/go" ]; then
|
||||||
|
missing="$pkg $missing"
|
||||||
|
fi
|
||||||
|
continue
|
||||||
|
fi
|
||||||
if [ "$pkg" == git ]; then
|
if [ "$pkg" == git ]; then
|
||||||
if ! which "git" >/dev/null; then
|
if ! which "git" >/dev/null; then
|
||||||
missing="git $missing"
|
missing="git $missing"
|
||||||
@@ -110,7 +132,25 @@ install() {
|
|||||||
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 git
|
||||||
|
|
||||||
for pkg in $1; do
|
for pkg in $1; do
|
||||||
|
if [ "$pkg" == custom-maven3.9.3 ]; then
|
||||||
|
install_custom_maven "3.9.3"
|
||||||
|
continue
|
||||||
|
fi
|
||||||
|
if [ "$pkg" == custom-golang1.18.9 ]; then
|
||||||
|
install_custom_golang "1.18.9"
|
||||||
|
continue
|
||||||
|
fi
|
||||||
|
if [ "$pkg" == jdk-17 ]; then
|
||||||
|
if ! yum list installed jdk-17 >/dev/null 2>/dev/null; then
|
||||||
|
wget https://download.oracle.com/java/17/latest/jdk-17_linux-x64_bin.rpm
|
||||||
|
rpm -ivh jdk-17_linux-x64_bin.rpm
|
||||||
|
update-alternatives --set java java-11-openjdk.x86_64
|
||||||
|
update-alternatives --set javac java-11-openjdk.x86_64
|
||||||
|
fi
|
||||||
|
continue
|
||||||
|
fi
|
||||||
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
|
||||||
yum install -y http://repo.okay.com.mx/centos/8/x86_64/release/libipt-1.6.1-8.el8.x86_64.rpm
|
yum install -y http://repo.okay.com.mx/centos/8/x86_64/release/libipt-1.6.1-8.el8.x86_64.rpm
|
||||||
|
|||||||
@@ -40,7 +40,7 @@ TOOLCHAIN_RUN_DEPS=(
|
|||||||
|
|
||||||
MEMGRAPH_BUILD_DEPS=(
|
MEMGRAPH_BUILD_DEPS=(
|
||||||
git # source code control
|
git # source code control
|
||||||
make pkgconf-pkg-config # build system
|
make cmake pkgconf-pkg-config # build system
|
||||||
wget # for downloading libs
|
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
|
||||||
@@ -56,10 +56,20 @@ MEMGRAPH_BUILD_DEPS=(
|
|||||||
libcurl-devel # mg-requests
|
libcurl-devel # mg-requests
|
||||||
rpm-build rpmlint # for RPM package building
|
rpm-build rpmlint # for RPM package building
|
||||||
doxygen graphviz # source documentation generators
|
doxygen graphviz # source documentation generators
|
||||||
which nodejs golang zip unzip java-11-openjdk-devel # for driver tests
|
which nodejs golang custom-golang1.18.9 # for driver tests
|
||||||
|
zip unzip java-11-openjdk-devel java-17-openjdk java-17-openjdk-devel custom-maven3.9.3 # for driver tests
|
||||||
sbcl # for custom Lisp C++ preprocessing
|
sbcl # for custom Lisp C++ preprocessing
|
||||||
autoconf # for jemalloc code generation
|
autoconf # for jemalloc code generation
|
||||||
libtool # for protobuf code generation
|
libtool # for protobuf code generation
|
||||||
|
cyrus-sasl-devel
|
||||||
|
)
|
||||||
|
|
||||||
|
MEMGRAPH_RUN_DEPS=(
|
||||||
|
logrotate openssl python3 libseccomp
|
||||||
|
)
|
||||||
|
|
||||||
|
NEW_DEPS=(
|
||||||
|
wget curl tar gzip
|
||||||
)
|
)
|
||||||
|
|
||||||
list() {
|
list() {
|
||||||
@@ -69,6 +79,18 @@ list() {
|
|||||||
check() {
|
check() {
|
||||||
local missing=""
|
local missing=""
|
||||||
for pkg in $1; do
|
for pkg in $1; do
|
||||||
|
if [ "$pkg" == custom-maven3.9.3 ]; then
|
||||||
|
if [ ! -f "/opt/apache-maven-3.9.3/bin/mvn" ]; then
|
||||||
|
missing="$pkg $missing"
|
||||||
|
fi
|
||||||
|
continue
|
||||||
|
fi
|
||||||
|
if [ "$pkg" == custom-golang1.18.9 ]; then
|
||||||
|
if [ ! -f "/opt/go1.18.9/go/bin/go" ]; then
|
||||||
|
missing="$pkg $missing"
|
||||||
|
fi
|
||||||
|
continue
|
||||||
|
fi
|
||||||
if [ "$pkg" == "PyYAML" ]; then
|
if [ "$pkg" == "PyYAML" ]; then
|
||||||
if ! python3 -c "import yaml" >/dev/null 2>/dev/null; then
|
if ! python3 -c "import yaml" >/dev/null 2>/dev/null; then
|
||||||
missing="$pkg $missing"
|
missing="$pkg $missing"
|
||||||
@@ -103,7 +125,16 @@ install() {
|
|||||||
fi
|
fi
|
||||||
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
|
||||||
|
if [ "$pkg" == custom-maven3.9.3 ]; then
|
||||||
|
install_custom_maven "3.9.3"
|
||||||
|
continue
|
||||||
|
fi
|
||||||
|
if [ "$pkg" == custom-golang1.18.9 ]; then
|
||||||
|
install_custom_golang "1.18.9"
|
||||||
|
continue
|
||||||
|
fi
|
||||||
# Since there is no support for libipt-devel for CentOS 9 we install
|
# 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
|
# Fedoras version of same libs, they are the same version but released
|
||||||
# for different OS
|
# for different OS
|
||||||
|
|||||||
@@ -40,7 +40,7 @@ TOOLCHAIN_RUN_DEPS=(
|
|||||||
|
|
||||||
MEMGRAPH_BUILD_DEPS=(
|
MEMGRAPH_BUILD_DEPS=(
|
||||||
git # source code control
|
git # source code control
|
||||||
make pkg-config # build system
|
make cmake pkg-config # build system
|
||||||
curl wget # for downloading libs
|
curl wget # for downloading libs
|
||||||
uuid-dev default-jre-headless # required by antlr
|
uuid-dev default-jre-headless # required by antlr
|
||||||
libreadline-dev # for memgraph console
|
libreadline-dev # for memgraph console
|
||||||
@@ -53,10 +53,19 @@ MEMGRAPH_BUILD_DEPS=(
|
|||||||
libcurl4-openssl-dev # mg-requests
|
libcurl4-openssl-dev # mg-requests
|
||||||
sbcl # for custom Lisp C++ preprocessing
|
sbcl # for custom Lisp C++ preprocessing
|
||||||
doxygen graphviz # source documentation generators
|
doxygen graphviz # source documentation generators
|
||||||
mono-runtime mono-mcs zip unzip default-jdk-headless # for driver tests
|
mono-runtime mono-mcs zip unzip default-jdk-headless oracle-java17-installer custom-maven3.9.3 # for driver tests
|
||||||
dotnet-sdk-3.1 golang nodejs npm
|
dotnet-sdk-3.1 golang custom-golang1.18.9 nodejs npm # for driver tests
|
||||||
autoconf # for jemalloc code generation
|
autoconf # for jemalloc code generation
|
||||||
libtool # for protobuf code generation
|
libtool # for protobuf code generation
|
||||||
|
libsasl2-dev
|
||||||
|
)
|
||||||
|
|
||||||
|
MEMGRAPH_RUN_DEPS=(
|
||||||
|
logrotate openssl python3 libseccomp
|
||||||
|
)
|
||||||
|
|
||||||
|
NEW_DEPS=(
|
||||||
|
wget curl tar gzip
|
||||||
)
|
)
|
||||||
|
|
||||||
list() {
|
list() {
|
||||||
@@ -64,7 +73,28 @@ list() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
check() {
|
check() {
|
||||||
check_all_dpkg "$1"
|
local missing=""
|
||||||
|
for pkg in $1; do
|
||||||
|
if [ "$pkg" == custom-maven3.9.3 ]; then
|
||||||
|
if [ ! -f "/opt/apache-maven-3.9.3/bin/mvn" ]; then
|
||||||
|
missing="$pkg $missing"
|
||||||
|
fi
|
||||||
|
continue
|
||||||
|
fi
|
||||||
|
if [ "$pkg" == custom-golang1.18.9 ]; then
|
||||||
|
if [ ! -f "/opt/go1.18.9/go/bin/go" ]; then
|
||||||
|
missing="$pkg $missing"
|
||||||
|
fi
|
||||||
|
continue
|
||||||
|
fi
|
||||||
|
if ! dpkg -s "$pkg" >/dev/null 2>/dev/null; then
|
||||||
|
missing="$pkg $missing"
|
||||||
|
fi
|
||||||
|
done
|
||||||
|
if [ "$missing" != "" ]; then
|
||||||
|
echo "MISSING PACKAGES: $missing"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
}
|
}
|
||||||
|
|
||||||
install() {
|
install() {
|
||||||
@@ -75,8 +105,15 @@ deb http://deb.debian.org/debian/ buster-updates main contrib non-free
|
|||||||
deb-src http://deb.debian.org/debian/ buster-updates main contrib non-free
|
deb-src http://deb.debian.org/debian/ buster-updates main contrib non-free
|
||||||
deb http://security.debian.org/debian-security buster/updates main contrib non-free
|
deb http://security.debian.org/debian-security buster/updates main contrib non-free
|
||||||
deb-src http://security.debian.org/debian-security buster/updates main contrib non-free
|
deb-src http://security.debian.org/debian-security buster/updates main contrib non-free
|
||||||
|
EOF
|
||||||
|
apt --allow-releaseinfo-change update
|
||||||
|
cat >/etc/apt/sources.list.d/java.list << EOF
|
||||||
|
deb http://ppa.launchpad.net/linuxuprising/java/ubuntu bionic main
|
||||||
|
deb-src http://ppa.launchpad.net/linuxuprising/java/ubuntu bionic main
|
||||||
EOF
|
EOF
|
||||||
cd "$DIR"
|
cd "$DIR"
|
||||||
|
apt install -y gnupg
|
||||||
|
apt-key adv --keyserver keyserver.ubuntu.com --recv-keys EA8CACC073C3DB2A
|
||||||
apt --allow-releaseinfo-change update
|
apt --allow-releaseinfo-change update
|
||||||
# If GitHub Actions runner is installed, append LANG to the environment.
|
# If GitHub Actions runner is installed, append LANG to the environment.
|
||||||
# Python related tests doesn't work the LANG export.
|
# Python related tests doesn't work the LANG export.
|
||||||
@@ -85,8 +122,26 @@ EOF
|
|||||||
else
|
else
|
||||||
echo "NOTE: export LANG=en_US.utf8"
|
echo "NOTE: export LANG=en_US.utf8"
|
||||||
fi
|
fi
|
||||||
apt install -y wget
|
|
||||||
for pkg in $1; do
|
for pkg in $1; do
|
||||||
|
if [ "$pkg" == custom-maven3.9.3 ]; then
|
||||||
|
install_custom_maven "3.9.3"
|
||||||
|
continue
|
||||||
|
fi
|
||||||
|
if [ "$pkg" == custom-golang1.18.9 ]; then
|
||||||
|
install_custom_golang "1.18.9"
|
||||||
|
continue
|
||||||
|
fi
|
||||||
|
if [ "$pkg" == oracle-java17-installer ]; then
|
||||||
|
if ! dpkg -s "$pkg" 2>/dev/null >/dev/null; then
|
||||||
|
echo oracle-java17-installer shared/accepted-oracle-license-v1-3 select true | /usr/bin/debconf-set-selections
|
||||||
|
echo oracle-java17-installer shared/accepted-oracle-license-v1-3 seen true | /usr/bin/debconf-set-selections
|
||||||
|
apt install -y "$pkg"
|
||||||
|
update-alternatives --set java /usr/lib/jvm/java-11-openjdk-amd64/bin/java
|
||||||
|
update-alternatives --set javac /usr/lib/jvm/java-11-openjdk-amd64/bin/javac
|
||||||
|
fi
|
||||||
|
continue
|
||||||
|
fi
|
||||||
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
|
||||||
|
|||||||
@@ -54,10 +54,19 @@ MEMGRAPH_BUILD_DEPS=(
|
|||||||
libcurl4-openssl-dev # mg-requests
|
libcurl4-openssl-dev # mg-requests
|
||||||
sbcl # for custom Lisp C++ preprocessing
|
sbcl # for custom Lisp C++ preprocessing
|
||||||
doxygen graphviz # source documentation generators
|
doxygen graphviz # source documentation generators
|
||||||
mono-runtime mono-mcs zip unzip default-jdk-headless # for driver tests
|
mono-runtime mono-mcs zip unzip default-jdk-headless openjdk-17-jdk custom-maven3.9.3 # for driver tests
|
||||||
golang nodejs npm
|
golang custom-golang1.18.9 nodejs npm
|
||||||
autoconf # for jemalloc code generation
|
autoconf # for jemalloc code generation
|
||||||
libtool # for protobuf code generation
|
libtool # for protobuf code generation
|
||||||
|
libsasl2-dev
|
||||||
|
)
|
||||||
|
|
||||||
|
MEMGRAPH_RUN_DEPS=(
|
||||||
|
logrotate openssl python3 libseccomp
|
||||||
|
)
|
||||||
|
|
||||||
|
NEW_DEPS=(
|
||||||
|
wget curl tar gzip
|
||||||
)
|
)
|
||||||
|
|
||||||
list() {
|
list() {
|
||||||
@@ -65,7 +74,28 @@ list() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
check() {
|
check() {
|
||||||
check_all_dpkg "$1"
|
local missing=""
|
||||||
|
for pkg in $1; do
|
||||||
|
if [ "$pkg" == custom-maven3.9.3 ]; then
|
||||||
|
if [ ! -f "/opt/apache-maven-3.9.3/bin/mvn" ]; then
|
||||||
|
missing="$pkg $missing"
|
||||||
|
fi
|
||||||
|
continue
|
||||||
|
fi
|
||||||
|
if [ "$pkg" == custom-golang1.18.9 ]; then
|
||||||
|
if [ ! -f "/opt/go1.18.9/go/bin/go" ]; then
|
||||||
|
missing="$pkg $missing"
|
||||||
|
fi
|
||||||
|
continue
|
||||||
|
fi
|
||||||
|
if ! dpkg -s "$pkg" >/dev/null 2>/dev/null; then
|
||||||
|
missing="$pkg $missing"
|
||||||
|
fi
|
||||||
|
done
|
||||||
|
if [ "$missing" != "" ]; then
|
||||||
|
echo "MISSING PACKAGES: $missing"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
}
|
}
|
||||||
|
|
||||||
install() {
|
install() {
|
||||||
@@ -89,7 +119,25 @@ EOF
|
|||||||
echo "NOTE: export LANG=en_US.utf8"
|
echo "NOTE: export LANG=en_US.utf8"
|
||||||
fi
|
fi
|
||||||
apt install -y wget
|
apt install -y wget
|
||||||
|
|
||||||
for pkg in $1; do
|
for pkg in $1; do
|
||||||
|
if [ "$pkg" == custom-maven3.9.3 ]; then
|
||||||
|
install_custom_maven "3.9.3"
|
||||||
|
continue
|
||||||
|
fi
|
||||||
|
if [ "$pkg" == custom-golang1.18.9 ]; then
|
||||||
|
install_custom_golang "1.18.9"
|
||||||
|
continue
|
||||||
|
fi
|
||||||
|
if [ "$pkg" == openjdk-17-jdk ]; then
|
||||||
|
if ! dpkg -s "$pkg" 2>/dev/null >/dev/null; then
|
||||||
|
apt install -y "$pkg"
|
||||||
|
# The default Java version should be Java 11
|
||||||
|
update-alternatives --set java /usr/lib/jvm/java-11-openjdk-arm64/bin/java
|
||||||
|
update-alternatives --set javac /usr/lib/jvm/java-11-openjdk-arm64/bin/javac
|
||||||
|
fi
|
||||||
|
continue
|
||||||
|
fi
|
||||||
apt install -y "$pkg"
|
apt install -y "$pkg"
|
||||||
done
|
done
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -41,7 +41,7 @@ TOOLCHAIN_RUN_DEPS=(
|
|||||||
|
|
||||||
MEMGRAPH_BUILD_DEPS=(
|
MEMGRAPH_BUILD_DEPS=(
|
||||||
git # source code control
|
git # source code control
|
||||||
make pkg-config # build system
|
make cmake pkg-config # build system
|
||||||
curl wget # for downloading libs
|
curl wget # for downloading libs
|
||||||
uuid-dev default-jre-headless # required by antlr
|
uuid-dev default-jre-headless # required by antlr
|
||||||
libreadline-dev # for memgraph console
|
libreadline-dev # for memgraph console
|
||||||
@@ -54,10 +54,19 @@ MEMGRAPH_BUILD_DEPS=(
|
|||||||
libcurl4-openssl-dev # mg-requests
|
libcurl4-openssl-dev # mg-requests
|
||||||
sbcl # for custom Lisp C++ preprocessing
|
sbcl # for custom Lisp C++ preprocessing
|
||||||
doxygen graphviz # source documentation generators
|
doxygen graphviz # source documentation generators
|
||||||
mono-runtime mono-mcs zip unzip default-jdk-headless # for driver tests
|
mono-runtime mono-mcs zip unzip default-jdk-headless openjdk-17-jdk custom-maven3.9.3 # for driver tests
|
||||||
dotnet-sdk-3.1 golang nodejs npm
|
dotnet-sdk-3.1 golang custom-golang1.18.9 nodejs npm
|
||||||
autoconf # for jemalloc code generation
|
autoconf # for jemalloc code generation
|
||||||
libtool # for protobuf code generation
|
libtool # for protobuf code generation
|
||||||
|
libsasl2-dev
|
||||||
|
)
|
||||||
|
|
||||||
|
MEMGRAPH_RUN_DEPS=(
|
||||||
|
logrotate openssl python3 libseccomp
|
||||||
|
)
|
||||||
|
|
||||||
|
NEW_DEPS=(
|
||||||
|
wget curl tar gzip
|
||||||
)
|
)
|
||||||
|
|
||||||
list() {
|
list() {
|
||||||
@@ -65,7 +74,28 @@ list() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
check() {
|
check() {
|
||||||
check_all_dpkg "$1"
|
local missing=""
|
||||||
|
for pkg in $1; do
|
||||||
|
if [ "$pkg" == custom-maven3.9.3 ]; then
|
||||||
|
if [ ! -f "/opt/apache-maven-3.9.3/bin/mvn" ]; then
|
||||||
|
missing="$pkg $missing"
|
||||||
|
fi
|
||||||
|
continue
|
||||||
|
fi
|
||||||
|
if [ "$pkg" == custom-golang1.18.9 ]; then
|
||||||
|
if [ ! -f "/opt/go1.18.9/go/bin/go" ]; then
|
||||||
|
missing="$pkg $missing"
|
||||||
|
fi
|
||||||
|
continue
|
||||||
|
fi
|
||||||
|
if ! dpkg -s "$pkg" >/dev/null 2>/dev/null; then
|
||||||
|
missing="$pkg $missing"
|
||||||
|
fi
|
||||||
|
done
|
||||||
|
if [ "$missing" != "" ]; then
|
||||||
|
echo "MISSING PACKAGES: $missing"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
}
|
}
|
||||||
|
|
||||||
install() {
|
install() {
|
||||||
@@ -89,7 +119,25 @@ EOF
|
|||||||
echo "NOTE: export LANG=en_US.utf8"
|
echo "NOTE: export LANG=en_US.utf8"
|
||||||
fi
|
fi
|
||||||
apt install -y wget
|
apt install -y wget
|
||||||
|
|
||||||
for pkg in $1; do
|
for pkg in $1; do
|
||||||
|
if [ "$pkg" == custom-maven3.9.3 ]; then
|
||||||
|
install_custom_maven "3.9.3"
|
||||||
|
continue
|
||||||
|
fi
|
||||||
|
if [ "$pkg" == custom-golang1.18.9 ]; then
|
||||||
|
install_custom_golang "1.18.9"
|
||||||
|
continue
|
||||||
|
fi
|
||||||
|
if [ "$pkg" == openjdk-17-jdk ]; then
|
||||||
|
if ! dpkg -s "$pkg" 2>/dev/null >/dev/null; then
|
||||||
|
apt install -y "$pkg"
|
||||||
|
# The default Java version should be Java 11
|
||||||
|
update-alternatives --set java /usr/lib/jvm/java-11-openjdk-amd64/bin/java
|
||||||
|
update-alternatives --set javac /usr/lib/jvm/java-11-openjdk-amd64/bin/javac
|
||||||
|
fi
|
||||||
|
continue
|
||||||
|
fi
|
||||||
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
|
||||||
|
|||||||
@@ -41,7 +41,7 @@ TOOLCHAIN_RUN_DEPS=(
|
|||||||
|
|
||||||
MEMGRAPH_BUILD_DEPS=(
|
MEMGRAPH_BUILD_DEPS=(
|
||||||
git # source code control
|
git # source code control
|
||||||
make pkgconf-pkg-config # build system
|
make cmake pkgconf-pkg-config # build system
|
||||||
wget # for downloading libs
|
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
|
||||||
@@ -52,10 +52,21 @@ MEMGRAPH_BUILD_DEPS=(
|
|||||||
libcurl-devel # mg-requests
|
libcurl-devel # mg-requests
|
||||||
rpm-build rpmlint # for RPM package building
|
rpm-build rpmlint # for RPM package building
|
||||||
doxygen graphviz # source documentation generators
|
doxygen graphviz # source documentation generators
|
||||||
which nodejs golang zip unzip java-11-openjdk-devel # for driver tests
|
java-11-openjdk-devel java-17-openjdk-devel custom-maven3.9.3 # for driver tests
|
||||||
|
which zip unzip
|
||||||
|
nodejs golang custom-golang1.18.9 # for driver tests
|
||||||
sbcl # for custom Lisp C++ preprocessing
|
sbcl # for custom Lisp C++ preprocessing
|
||||||
autoconf # for jemalloc code generation
|
autoconf # for jemalloc code generation
|
||||||
libtool # for protobuf code generation
|
libtool # for protobuf code generation
|
||||||
|
cyrus-sasl-devel
|
||||||
|
)
|
||||||
|
|
||||||
|
MEMGRAPH_RUN_DEPS=(
|
||||||
|
logrotate openssl python3 libseccomp
|
||||||
|
)
|
||||||
|
|
||||||
|
NEW_DEPS=(
|
||||||
|
wget curl tar gzip
|
||||||
)
|
)
|
||||||
|
|
||||||
list() {
|
list() {
|
||||||
@@ -64,11 +75,25 @@ list() {
|
|||||||
|
|
||||||
check() {
|
check() {
|
||||||
local missing=""
|
local missing=""
|
||||||
# On Fedora yum/dnf and python10 use newer glibc which is not compatible
|
if [ -v LD_LIBRARY_PATH ]; then
|
||||||
# with ours, so we need to momentarely disable env
|
# On Fedora yum/dnf and python10 use newer glibc which is not compatible
|
||||||
local OLD_LD_LIBRARY_PATH=${LD_LIBRARY_PATH}
|
# with ours, so we need to momentarely disable env
|
||||||
LD_LIBRARY_PATH=""
|
local OLD_LD_LIBRARY_PATH=${LD_LIBRARY_PATH}
|
||||||
|
LD_LIBRARY_PATH=""
|
||||||
|
fi
|
||||||
for pkg in $1; do
|
for pkg in $1; do
|
||||||
|
if [ "$pkg" == custom-maven3.9.3 ]; then
|
||||||
|
if [ ! -f "/opt/apache-maven-3.9.3/bin/mvn" ]; then
|
||||||
|
missing="$pkg $missing"
|
||||||
|
fi
|
||||||
|
continue
|
||||||
|
fi
|
||||||
|
if [ "$pkg" == custom-golang1.18.9 ]; then
|
||||||
|
if [ ! -f "/opt/go1.18.9/go/bin/go" ]; then
|
||||||
|
missing="$pkg $missing"
|
||||||
|
fi
|
||||||
|
continue
|
||||||
|
fi
|
||||||
if ! dnf list installed "$pkg" >/dev/null 2>/dev/null; then
|
if ! dnf list installed "$pkg" >/dev/null 2>/dev/null; then
|
||||||
missing="$pkg $missing"
|
missing="$pkg $missing"
|
||||||
fi
|
fi
|
||||||
@@ -77,7 +102,10 @@ check() {
|
|||||||
echo "MISSING PACKAGES: $missing"
|
echo "MISSING PACKAGES: $missing"
|
||||||
exit 1
|
exit 1
|
||||||
fi
|
fi
|
||||||
LD_LIBRARY_PATH=${OLD_LD_LIBRARY_PATH}
|
if [ -v OLD_LD_LIBRARY_PATH ]; then
|
||||||
|
echo "Restoring LD_LIBRARY_PATH..."
|
||||||
|
LD_LIBRARY_PATH=${OLD_LD_LIBRARY_PATH}
|
||||||
|
fi
|
||||||
}
|
}
|
||||||
|
|
||||||
install() {
|
install() {
|
||||||
@@ -94,7 +122,25 @@ install() {
|
|||||||
echo "NOTE: export LANG=en_US.utf8"
|
echo "NOTE: export LANG=en_US.utf8"
|
||||||
fi
|
fi
|
||||||
dnf update -y
|
dnf update -y
|
||||||
|
|
||||||
for pkg in $1; do
|
for pkg in $1; do
|
||||||
|
if [ "$pkg" == custom-maven3.9.3 ]; then
|
||||||
|
install_custom_maven "3.9.3"
|
||||||
|
continue
|
||||||
|
fi
|
||||||
|
if [ "$pkg" == custom-golang1.18.9 ]; then
|
||||||
|
install_custom_golang "1.18.9"
|
||||||
|
continue
|
||||||
|
fi
|
||||||
|
if [ "$pkg" == java-17-openjdk-devel ]; then
|
||||||
|
if ! dnf list installed "$pkg" >/dev/null 2>/dev/null; then
|
||||||
|
dnf install -y "$pkg"
|
||||||
|
# The default Java version should be Java 11
|
||||||
|
update-alternatives --set java java-11-openjdk.x86_64
|
||||||
|
update-alternatives --set javac java-11-openjdk.x86_64
|
||||||
|
fi
|
||||||
|
continue
|
||||||
|
fi
|
||||||
dnf install -y "$pkg"
|
dnf install -y "$pkg"
|
||||||
done
|
done
|
||||||
}
|
}
|
||||||
|
|||||||
145
environment/os/run.sh
Executable file
145
environment/os/run.sh
Executable file
@@ -0,0 +1,145 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
set -Eeuo pipefail
|
||||||
|
SCRIPT_DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" >/dev/null 2>&1 && pwd )"
|
||||||
|
IFS=' '
|
||||||
|
# NOTE: docker_image_name could be local image build based on release/package images.
|
||||||
|
# NOTE: each line has to be under quotes, docker_container_type, script_name and docker_image_name separate with a space.
|
||||||
|
# "docker_container_type script_name docker_image_name"
|
||||||
|
OPERATING_SYSTEMS=(
|
||||||
|
"mgrun amzn-2 amazonlinux:2"
|
||||||
|
"mgrun centos-7 centos:7"
|
||||||
|
"mgrun centos-9 dokken/centos-stream-9"
|
||||||
|
"mgrun debian-10 debian:10"
|
||||||
|
"mgrun debian-11 debian:11"
|
||||||
|
"mgrun fedora-36 fedora:36"
|
||||||
|
"mgrun ubuntu-18.04 ubuntu:18.04"
|
||||||
|
"mgrun ubuntu-20.04 ubuntu:20.04"
|
||||||
|
"mgrun ubuntu-22.04 ubuntu:22.04"
|
||||||
|
# "mgbuild centos-7 package-mgbuild_centos-7"
|
||||||
|
)
|
||||||
|
|
||||||
|
if [ ! "$(docker info)" ]; then
|
||||||
|
echo "ERROR: Docker is required"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
print_help () {
|
||||||
|
echo -e "$0 all\t\t\t\t => start + init all containers in the background"
|
||||||
|
echo -e "$0 check\t\t\t\t => check all containers"
|
||||||
|
echo -e "$0 delete\t\t\t\t => stop + remove all containers"
|
||||||
|
echo -e "$0 copy src_container dst_container => copy build package from src to dst container"
|
||||||
|
exit 1
|
||||||
|
}
|
||||||
|
|
||||||
|
# NOTE: This is an idempotent operation!
|
||||||
|
# TODO(gitbuda): Consider making docker_run always delete + start a new container or add a new function.
|
||||||
|
docker_run () {
|
||||||
|
cnt_name="$1"
|
||||||
|
cnt_image="$2"
|
||||||
|
if [ ! "$(docker ps -q -f name=$cnt_name)" ]; then
|
||||||
|
if [ "$(docker ps -aq -f status=exited -f name=$cnt_name)" ]; then
|
||||||
|
echo "Cleanup of the old exited container..."
|
||||||
|
docker rm $cnt_name
|
||||||
|
fi
|
||||||
|
docker run -d --volume "$SCRIPT_DIR/../../:/memgraph" --network host --name "$cnt_name" "$cnt_image" sleep infinity
|
||||||
|
fi
|
||||||
|
echo "The $cnt_image container is active under $cnt_name name!"
|
||||||
|
}
|
||||||
|
|
||||||
|
docker_exec () {
|
||||||
|
cnt_name="$1"
|
||||||
|
cnt_cmd="$2"
|
||||||
|
docker exec -it "$cnt_name" bash -c "$cnt_cmd"
|
||||||
|
}
|
||||||
|
|
||||||
|
docker_stop_and_rm () {
|
||||||
|
cnt_name="$1"
|
||||||
|
if [ "$(docker ps -q -f name=$cnt_name)" ]; then
|
||||||
|
docker stop "$1"
|
||||||
|
if [ "$(docker ps -aq -f status=exited -f name=$cnt_name)" ]; then
|
||||||
|
docker rm "$1"
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
# TODO(gitbuda): Make the call to `install NEW_DEPS` configurable, the question what else is useful?
|
||||||
|
start_all () {
|
||||||
|
for script_docker_pair in "${OPERATING_SYSTEMS[@]}"; do
|
||||||
|
read -a script_docker <<< "$script_docker_pair"
|
||||||
|
docker_container_type="${script_docker[0]}"
|
||||||
|
script_name="${script_docker[1]}"
|
||||||
|
docker_image="${script_docker[2]}"
|
||||||
|
docker_name="${docker_container_type}_$script_name"
|
||||||
|
echo ""
|
||||||
|
echo "~~~~ OPERATING ON $docker_image as $docker_name..."
|
||||||
|
docker_run "$docker_name" "$docker_image"
|
||||||
|
docker_exec "$docker_name" "/memgraph/environment/os/$script_name.sh install NEW_DEPS"
|
||||||
|
echo "---- DONE EVERYHING FOR $docker_image as $docker_name..."
|
||||||
|
echo ""
|
||||||
|
done
|
||||||
|
}
|
||||||
|
|
||||||
|
check_all () {
|
||||||
|
for script_docker_pair in "${OPERATING_SYSTEMS[@]}"; do
|
||||||
|
read -a script_docker <<< "$script_docker_pair"
|
||||||
|
docker_container_type="${script_docker[0]}"
|
||||||
|
script_name="${script_docker[1]}"
|
||||||
|
docker_image="${script_docker[2]}"
|
||||||
|
docker_name="${docker_container_type}_$script_name"
|
||||||
|
echo ""
|
||||||
|
echo "~~~~ OPERATING ON $docker_image as $docker_name..."
|
||||||
|
docker_exec "$docker_name" "/memgraph/environment/os/$script_name.sh check NEW_DEPS"
|
||||||
|
echo "---- DONE EVERYHING FOR $docker_image as $docker_name..."
|
||||||
|
echo ""
|
||||||
|
done
|
||||||
|
}
|
||||||
|
|
||||||
|
delete_all () {
|
||||||
|
for script_docker_pair in "${OPERATING_SYSTEMS[@]}"; do
|
||||||
|
read -a script_docker <<< "$script_docker_pair"
|
||||||
|
docker_container_type="${script_docker[0]}"
|
||||||
|
script_name="${script_docker[1]}"
|
||||||
|
docker_image="${script_docker[2]}"
|
||||||
|
docker_name="${docker_container_type}_$script_name"
|
||||||
|
docker_stop_and_rm "$docker_name"
|
||||||
|
echo "~~~~ $docker_image as $docker_name DELETED"
|
||||||
|
done
|
||||||
|
}
|
||||||
|
|
||||||
|
# TODO(gitbuda): Copy file between containers is a useful util, also delete, + consider copying of a whole folder.
|
||||||
|
# TODO(gitbuda): Add args: src_cnt dst_cnt abs_path; both file and recursive folder, always delete + copy.
|
||||||
|
copy_build_package () {
|
||||||
|
src_container="$1"
|
||||||
|
dst_container="$2"
|
||||||
|
src="$src_container:/memgraph/build/output"
|
||||||
|
tmp_dst="$SCRIPT_DIR/../../build"
|
||||||
|
mkdir -p "$tmp_dst"
|
||||||
|
rm -rf "$tmp_dst/output"
|
||||||
|
dst="$dst_container:/"
|
||||||
|
docker cp "$src" "$tmp_dst"
|
||||||
|
docker cp "$tmp_dst/output" "$dst"
|
||||||
|
}
|
||||||
|
|
||||||
|
if [ "$#" -eq 0 ]; then
|
||||||
|
print_help
|
||||||
|
else
|
||||||
|
case $1 in
|
||||||
|
all)
|
||||||
|
start_all
|
||||||
|
;;
|
||||||
|
check)
|
||||||
|
check_all
|
||||||
|
;;
|
||||||
|
delete)
|
||||||
|
delete_all
|
||||||
|
;;
|
||||||
|
copy) # src_container dst_container
|
||||||
|
if [ "$#" -ne 3 ]; then
|
||||||
|
print_help
|
||||||
|
fi
|
||||||
|
copy_build_package "$2" "$3"
|
||||||
|
;;
|
||||||
|
*)
|
||||||
|
print_help
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
fi
|
||||||
@@ -6,6 +6,7 @@ DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" >/dev/null 2>&1 && pwd )"
|
|||||||
source "$DIR/../util.sh"
|
source "$DIR/../util.sh"
|
||||||
|
|
||||||
check_operating_system "todo-os-name"
|
check_operating_system "todo-os-name"
|
||||||
|
check_architecture "todo-arch-name"
|
||||||
|
|
||||||
TOOLCHAIN_BUILD_DEPS=(
|
TOOLCHAIN_BUILD_DEPS=(
|
||||||
pkg
|
pkg
|
||||||
@@ -19,6 +20,16 @@ MEMGRAPH_BUILD_DEPS=(
|
|||||||
pkg
|
pkg
|
||||||
)
|
)
|
||||||
|
|
||||||
|
MEMGRAPH_RUN_DEPS=(
|
||||||
|
pkg
|
||||||
|
)
|
||||||
|
|
||||||
|
# NEW_DEPS is useful when you won't to test the installation of a new package.
|
||||||
|
# During the test you can put here packages like wget curl tar gzip
|
||||||
|
NEW_DEPS=(
|
||||||
|
pkg
|
||||||
|
)
|
||||||
|
|
||||||
list() {
|
list() {
|
||||||
echo "$1"
|
echo "$1"
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -41,7 +41,7 @@ TOOLCHAIN_RUN_DEPS=(
|
|||||||
|
|
||||||
MEMGRAPH_BUILD_DEPS=(
|
MEMGRAPH_BUILD_DEPS=(
|
||||||
git # source code control
|
git # source code control
|
||||||
make pkg-config # build system
|
make cmake pkg-config # build system
|
||||||
curl wget # downloading libs
|
curl wget # downloading libs
|
||||||
uuid-dev default-jre-headless # required by antlr
|
uuid-dev default-jre-headless # required by antlr
|
||||||
libreadline-dev # memgraph console
|
libreadline-dev # memgraph console
|
||||||
@@ -53,9 +53,19 @@ MEMGRAPH_BUILD_DEPS=(
|
|||||||
libcurl4-openssl-dev # mg-requests
|
libcurl4-openssl-dev # mg-requests
|
||||||
sbcl # custom Lisp C++ preprocessing
|
sbcl # custom Lisp C++ preprocessing
|
||||||
doxygen graphviz # source documentation generators
|
doxygen graphviz # source documentation generators
|
||||||
mono-runtime mono-mcs nodejs zip unzip default-jdk-headless # driver tests
|
mono-runtime mono-mcs nodejs zip unzip default-jdk-headless openjdk-17-jdk-headless custom-maven3.9.3 # driver tests
|
||||||
|
custom-golang1.18.9 # for driver tests
|
||||||
autoconf # for jemalloc code generation
|
autoconf # for jemalloc code generation
|
||||||
libtool # for protobuf code generation
|
libtool # for protobuf code generation
|
||||||
|
libsasl2-dev
|
||||||
|
)
|
||||||
|
|
||||||
|
MEMGRAPH_RUN_DEPS=(
|
||||||
|
logrotate openssl python3 libseccomp2
|
||||||
|
)
|
||||||
|
|
||||||
|
NEW_DEPS=(
|
||||||
|
wget curl tar gzip
|
||||||
)
|
)
|
||||||
|
|
||||||
list() {
|
list() {
|
||||||
@@ -63,11 +73,53 @@ list() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
check() {
|
check() {
|
||||||
check_all_dpkg "$1"
|
local missing=""
|
||||||
|
for pkg in $1; do
|
||||||
|
if [ "$pkg" == custom-maven3.9.3 ]; then
|
||||||
|
if [ ! -f "/opt/apache-maven-3.9.3/bin/mvn" ]; then
|
||||||
|
missing="$pkg $missing"
|
||||||
|
fi
|
||||||
|
continue
|
||||||
|
fi
|
||||||
|
if [ "$pkg" == custom-golang1.18.9 ]; then
|
||||||
|
if [ ! -f "/opt/go1.18.9/go/bin/go" ]; then
|
||||||
|
missing="$pkg $missing"
|
||||||
|
fi
|
||||||
|
continue
|
||||||
|
fi
|
||||||
|
if ! dpkg -s "$pkg" >/dev/null 2>/dev/null; then
|
||||||
|
missing="$pkg $missing"
|
||||||
|
fi
|
||||||
|
done
|
||||||
|
if [ "$missing" != "" ]; then
|
||||||
|
echo "MISSING PACKAGES: $missing"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
}
|
}
|
||||||
|
|
||||||
install() {
|
install() {
|
||||||
apt install -y $1
|
apt update -y
|
||||||
|
|
||||||
|
for pkg in $1; do
|
||||||
|
if [ "$pkg" == custom-maven3.9.3 ]; then
|
||||||
|
install_custom_maven "3.9.3"
|
||||||
|
continue
|
||||||
|
fi
|
||||||
|
if [ "$pkg" == custom-golang1.18.9 ]; then
|
||||||
|
install_custom_golang "1.18.9"
|
||||||
|
continue
|
||||||
|
fi
|
||||||
|
if [ "$pkg" == openjdk-17-jdk-headless ]; then
|
||||||
|
if ! dpkg -s "$pkg" 2>/dev/null >/dev/null; then
|
||||||
|
apt install -y "$pkg"
|
||||||
|
# The default Java version should be Java 11
|
||||||
|
update-alternatives --set java /usr/lib/jvm/java-11-openjdk-amd64/bin/java
|
||||||
|
update-alternatives --set javac /usr/lib/jvm/java-11-openjdk-amd64/bin/javac
|
||||||
|
fi
|
||||||
|
continue
|
||||||
|
fi
|
||||||
|
apt install -y "$pkg"
|
||||||
|
done
|
||||||
}
|
}
|
||||||
|
|
||||||
deps=$2"[*]"
|
deps=$2"[*]"
|
||||||
|
|||||||
@@ -40,7 +40,7 @@ TOOLCHAIN_RUN_DEPS=(
|
|||||||
|
|
||||||
MEMGRAPH_BUILD_DEPS=(
|
MEMGRAPH_BUILD_DEPS=(
|
||||||
git # source code control
|
git # source code control
|
||||||
make pkg-config # build system
|
make cmake pkg-config # build system
|
||||||
curl wget # for downloading libs
|
curl wget # for downloading libs
|
||||||
uuid-dev default-jre-headless # required by antlr
|
uuid-dev default-jre-headless # required by antlr
|
||||||
libreadline-dev # for memgraph console
|
libreadline-dev # for memgraph console
|
||||||
@@ -53,10 +53,19 @@ MEMGRAPH_BUILD_DEPS=(
|
|||||||
libcurl4-openssl-dev # mg-requests
|
libcurl4-openssl-dev # mg-requests
|
||||||
sbcl # for custom Lisp C++ preprocessing
|
sbcl # for custom Lisp C++ preprocessing
|
||||||
doxygen graphviz # source documentation generators
|
doxygen graphviz # source documentation generators
|
||||||
mono-runtime mono-mcs zip unzip default-jdk-headless # for driver tests
|
mono-runtime mono-mcs zip unzip default-jdk-headless openjdk-17-jdk-headless custom-maven3.9.3 # for driver tests
|
||||||
dotnet-sdk-3.1 golang nodejs npm
|
dotnet-sdk-3.1 golang custom-golang1.18.9 nodejs npm # for driver tests
|
||||||
autoconf # for jemalloc code generation
|
autoconf # for jemalloc code generation
|
||||||
libtool # for protobuf code generation
|
libtool # for protobuf code generation
|
||||||
|
libsasl2-dev
|
||||||
|
)
|
||||||
|
|
||||||
|
MEMGRAPH_RUN_DEPS=(
|
||||||
|
logrotate openssl python3 libseccomp2
|
||||||
|
)
|
||||||
|
|
||||||
|
NEW_DEPS=(
|
||||||
|
wget curl tar gzip
|
||||||
)
|
)
|
||||||
|
|
||||||
list() {
|
list() {
|
||||||
@@ -64,12 +73,35 @@ list() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
check() {
|
check() {
|
||||||
check_all_dpkg "$1"
|
local missing=""
|
||||||
|
for pkg in $1; do
|
||||||
|
if [ "$pkg" == custom-maven3.9.3 ]; then
|
||||||
|
if [ ! -f "/opt/apache-maven-3.9.3/bin/mvn" ]; then
|
||||||
|
missing="$pkg $missing"
|
||||||
|
fi
|
||||||
|
continue
|
||||||
|
fi
|
||||||
|
if [ "$pkg" == custom-golang1.18.9 ]; then
|
||||||
|
if [ ! -f "/opt/go1.18.9/go/bin/go" ]; then
|
||||||
|
missing="$pkg $missing"
|
||||||
|
fi
|
||||||
|
continue
|
||||||
|
fi
|
||||||
|
if ! dpkg -s "$pkg" >/dev/null 2>/dev/null; then
|
||||||
|
missing="$pkg $missing"
|
||||||
|
fi
|
||||||
|
done
|
||||||
|
if [ "$missing" != "" ]; then
|
||||||
|
echo "MISSING PACKAGES: $missing"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
}
|
}
|
||||||
|
|
||||||
install() {
|
install() {
|
||||||
cd "$DIR"
|
cd "$DIR"
|
||||||
apt update
|
export DEBIAN_FRONTEND=noninteractive
|
||||||
|
apt update -y
|
||||||
|
apt install -y wget
|
||||||
# If GitHub Actions runner is installed, append LANG to the environment.
|
# If GitHub Actions runner is installed, append LANG to the environment.
|
||||||
# Python related tests doesn't work the LANG export.
|
# Python related tests doesn't work the LANG export.
|
||||||
if [ -d "/home/gh/actions-runner" ]; then
|
if [ -d "/home/gh/actions-runner" ]; then
|
||||||
@@ -77,8 +109,16 @@ install() {
|
|||||||
else
|
else
|
||||||
echo "NOTE: export LANG=en_US.utf8"
|
echo "NOTE: export LANG=en_US.utf8"
|
||||||
fi
|
fi
|
||||||
apt install -y wget
|
|
||||||
for pkg in $1; do
|
for pkg in $1; do
|
||||||
|
if [ "$pkg" == custom-maven3.9.3 ]; then
|
||||||
|
install_custom_maven "3.9.3"
|
||||||
|
continue
|
||||||
|
fi
|
||||||
|
if [ "$pkg" == custom-golang1.18.9 ]; then
|
||||||
|
install_custom_golang "1.18.9"
|
||||||
|
continue
|
||||||
|
fi
|
||||||
if [ "$pkg" == dotnet-sdk-3.1 ]; then
|
if [ "$pkg" == dotnet-sdk-3.1 ]; then
|
||||||
if ! dpkg -s dotnet-sdk-3.1 2>/dev/null >/dev/null; then
|
if ! dpkg -s dotnet-sdk-3.1 2>/dev/null >/dev/null; then
|
||||||
wget -nv https://packages.microsoft.com/config/ubuntu/20.04/packages-microsoft-prod.deb -O packages-microsoft-prod.deb
|
wget -nv https://packages.microsoft.com/config/ubuntu/20.04/packages-microsoft-prod.deb -O packages-microsoft-prod.deb
|
||||||
@@ -88,6 +128,15 @@ install() {
|
|||||||
fi
|
fi
|
||||||
continue
|
continue
|
||||||
fi
|
fi
|
||||||
|
if [ "$pkg" == openjdk-17-jdk-headless ]; then
|
||||||
|
if ! dpkg -s "$pkg" 2>/dev/null >/dev/null; then
|
||||||
|
apt install -y "$pkg"
|
||||||
|
# The default Java version should be Java 11
|
||||||
|
update-alternatives --set java /usr/lib/jvm/java-11-openjdk-amd64/bin/java
|
||||||
|
update-alternatives --set javac /usr/lib/jvm/java-11-openjdk-amd64/bin/javac
|
||||||
|
fi
|
||||||
|
continue
|
||||||
|
fi
|
||||||
apt install -y "$pkg"
|
apt install -y "$pkg"
|
||||||
done
|
done
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -40,7 +40,7 @@ TOOLCHAIN_RUN_DEPS=(
|
|||||||
|
|
||||||
MEMGRAPH_BUILD_DEPS=(
|
MEMGRAPH_BUILD_DEPS=(
|
||||||
git # source code control
|
git # source code control
|
||||||
make pkg-config # build system
|
make cmake pkg-config # build system
|
||||||
curl wget # for downloading libs
|
curl wget # for downloading libs
|
||||||
uuid-dev default-jre-headless # required by antlr
|
uuid-dev default-jre-headless # required by antlr
|
||||||
libreadline-dev # for memgraph console
|
libreadline-dev # for memgraph console
|
||||||
@@ -53,10 +53,19 @@ MEMGRAPH_BUILD_DEPS=(
|
|||||||
libcurl4-openssl-dev # mg-requests
|
libcurl4-openssl-dev # mg-requests
|
||||||
sbcl # for custom Lisp C++ preprocessing
|
sbcl # for custom Lisp C++ preprocessing
|
||||||
doxygen graphviz # source documentation generators
|
doxygen graphviz # source documentation generators
|
||||||
mono-runtime mono-mcs zip unzip default-jdk-headless # for driver tests
|
mono-runtime mono-mcs zip unzip default-jdk-headless openjdk-17-jdk-headless custom-maven3.9.3 # for driver tests
|
||||||
dotnet-sdk-6.0 golang nodejs npm
|
dotnet-sdk-6.0 golang custom-golang1.18.9 nodejs npm
|
||||||
autoconf # for jemalloc code generation
|
autoconf # for jemalloc code generation
|
||||||
libtool # for protobuf code generation
|
libtool # for protobuf code generation
|
||||||
|
libsasl2-dev
|
||||||
|
)
|
||||||
|
|
||||||
|
MEMGRAPH_RUN_DEPS=(
|
||||||
|
logrotate openssl python3 libseccomp2
|
||||||
|
)
|
||||||
|
|
||||||
|
NEW_DEPS=(
|
||||||
|
wget curl tar gzip
|
||||||
)
|
)
|
||||||
|
|
||||||
list() {
|
list() {
|
||||||
@@ -64,7 +73,28 @@ list() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
check() {
|
check() {
|
||||||
check_all_dpkg "$1"
|
local missing=""
|
||||||
|
for pkg in $1; do
|
||||||
|
if [ "$pkg" == custom-maven3.9.3 ]; then
|
||||||
|
if [ ! -f "/opt/apache-maven-3.9.3/bin/mvn" ]; then
|
||||||
|
missing="$pkg $missing"
|
||||||
|
fi
|
||||||
|
continue
|
||||||
|
fi
|
||||||
|
if [ "$pkg" == custom-golang1.18.9 ]; then
|
||||||
|
if [ ! -f "/opt/go1.18.9/go/bin/go" ]; then
|
||||||
|
missing="$pkg $missing"
|
||||||
|
fi
|
||||||
|
continue
|
||||||
|
fi
|
||||||
|
if ! dpkg -s "$pkg" >/dev/null 2>/dev/null; then
|
||||||
|
missing="$pkg $missing"
|
||||||
|
fi
|
||||||
|
done
|
||||||
|
if [ "$missing" != "" ]; then
|
||||||
|
echo "MISSING PACKAGES: $missing"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
}
|
}
|
||||||
|
|
||||||
install() {
|
install() {
|
||||||
@@ -78,7 +108,16 @@ install() {
|
|||||||
echo "NOTE: export LANG=en_US.utf8"
|
echo "NOTE: export LANG=en_US.utf8"
|
||||||
fi
|
fi
|
||||||
apt install -y wget
|
apt install -y wget
|
||||||
|
|
||||||
for pkg in $1; do
|
for pkg in $1; do
|
||||||
|
if [ "$pkg" == custom-maven3.9.3 ]; then
|
||||||
|
install_custom_maven "3.9.3"
|
||||||
|
continue
|
||||||
|
fi
|
||||||
|
if [ "$pkg" == custom-golang1.18.9 ]; then
|
||||||
|
install_custom_golang "1.18.9"
|
||||||
|
continue
|
||||||
|
fi
|
||||||
if [ "$pkg" == dotnet-sdk-6.0 ]; then
|
if [ "$pkg" == dotnet-sdk-6.0 ]; then
|
||||||
if ! dpkg -s dotnet-sdk-6.0 2>/dev/null >/dev/null; 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
|
wget -nv https://packages.microsoft.com/config/ubuntu/22.04/packages-microsoft-prod.deb -O packages-microsoft-prod.deb
|
||||||
@@ -88,6 +127,15 @@ install() {
|
|||||||
fi
|
fi
|
||||||
continue
|
continue
|
||||||
fi
|
fi
|
||||||
|
if [ "$pkg" == openjdk-17-jdk-headless ]; then
|
||||||
|
if ! dpkg -s "$pkg" 2>/dev/null >/dev/null; then
|
||||||
|
apt install -y "$pkg"
|
||||||
|
# The default Java version should be Java 11
|
||||||
|
update-alternatives --set java /usr/lib/jvm/java-11-openjdk-arm64/bin/java
|
||||||
|
update-alternatives --set javac /usr/lib/jvm/java-11-openjdk-arm64/bin/javac
|
||||||
|
fi
|
||||||
|
continue
|
||||||
|
fi
|
||||||
apt install -y "$pkg"
|
apt install -y "$pkg"
|
||||||
done
|
done
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -40,7 +40,7 @@ TOOLCHAIN_RUN_DEPS=(
|
|||||||
|
|
||||||
MEMGRAPH_BUILD_DEPS=(
|
MEMGRAPH_BUILD_DEPS=(
|
||||||
git # source code control
|
git # source code control
|
||||||
make pkg-config # build system
|
make cmake pkg-config # build system
|
||||||
curl wget # for downloading libs
|
curl wget # for downloading libs
|
||||||
uuid-dev default-jre-headless # required by antlr
|
uuid-dev default-jre-headless # required by antlr
|
||||||
libreadline-dev # for memgraph console
|
libreadline-dev # for memgraph console
|
||||||
@@ -53,10 +53,19 @@ MEMGRAPH_BUILD_DEPS=(
|
|||||||
libcurl4-openssl-dev # mg-requests
|
libcurl4-openssl-dev # mg-requests
|
||||||
sbcl # for custom Lisp C++ preprocessing
|
sbcl # for custom Lisp C++ preprocessing
|
||||||
doxygen graphviz # source documentation generators
|
doxygen graphviz # source documentation generators
|
||||||
mono-runtime mono-mcs zip unzip default-jdk-headless # for driver tests
|
mono-runtime mono-mcs zip unzip default-jdk-headless openjdk-17-jdk-headless custom-maven3.9.3 # for driver tests
|
||||||
dotnet-sdk-6.0 golang nodejs npm
|
dotnet-sdk-6.0 golang custom-golang1.18.9 nodejs npm # for driver tests
|
||||||
autoconf # for jemalloc code generation
|
autoconf # for jemalloc code generation
|
||||||
libtool # for protobuf code generation
|
libtool # for protobuf code generation
|
||||||
|
libsasl2-dev
|
||||||
|
)
|
||||||
|
|
||||||
|
MEMGRAPH_RUN_DEPS=(
|
||||||
|
logrotate openssl python3 libseccomp2
|
||||||
|
)
|
||||||
|
|
||||||
|
NEW_DEPS=(
|
||||||
|
wget curl tar gzip
|
||||||
)
|
)
|
||||||
|
|
||||||
list() {
|
list() {
|
||||||
@@ -64,12 +73,34 @@ list() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
check() {
|
check() {
|
||||||
check_all_dpkg "$1"
|
local missing=""
|
||||||
|
for pkg in $1; do
|
||||||
|
if [ "$pkg" == custom-maven3.9.3 ]; then
|
||||||
|
if [ ! -f "/opt/apache-maven-3.9.3/bin/mvn" ]; then
|
||||||
|
missing="$pkg $missing"
|
||||||
|
fi
|
||||||
|
continue
|
||||||
|
fi
|
||||||
|
if [ "$pkg" == custom-golang1.18.9 ]; then
|
||||||
|
if [ ! -f "/opt/go1.18.9/go/bin/go" ]; then
|
||||||
|
missing="$pkg $missing"
|
||||||
|
fi
|
||||||
|
continue
|
||||||
|
fi
|
||||||
|
if ! dpkg -s "$pkg" >/dev/null 2>/dev/null; then
|
||||||
|
missing="$pkg $missing"
|
||||||
|
fi
|
||||||
|
done
|
||||||
|
if [ "$missing" != "" ]; then
|
||||||
|
echo "MISSING PACKAGES: $missing"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
}
|
}
|
||||||
|
|
||||||
install() {
|
install() {
|
||||||
cd "$DIR"
|
cd "$DIR"
|
||||||
apt update
|
apt update -y
|
||||||
|
apt install -y wget
|
||||||
# If GitHub Actions runner is installed, append LANG to the environment.
|
# If GitHub Actions runner is installed, append LANG to the environment.
|
||||||
# Python related tests doesn't work the LANG export.
|
# Python related tests doesn't work the LANG export.
|
||||||
if [ -d "/home/gh/actions-runner" ]; then
|
if [ -d "/home/gh/actions-runner" ]; then
|
||||||
@@ -77,8 +108,16 @@ install() {
|
|||||||
else
|
else
|
||||||
echo "NOTE: export LANG=en_US.utf8"
|
echo "NOTE: export LANG=en_US.utf8"
|
||||||
fi
|
fi
|
||||||
apt install -y wget
|
|
||||||
for pkg in $1; do
|
for pkg in $1; do
|
||||||
|
if [ "$pkg" == custom-maven3.9.3 ]; then
|
||||||
|
install_custom_maven "3.9.3"
|
||||||
|
continue
|
||||||
|
fi
|
||||||
|
if [ "$pkg" == custom-golang1.18.9 ]; then
|
||||||
|
install_custom_golang "1.18.9"
|
||||||
|
continue
|
||||||
|
fi
|
||||||
if [ "$pkg" == dotnet-sdk-6.0 ]; then
|
if [ "$pkg" == dotnet-sdk-6.0 ]; then
|
||||||
if ! dpkg -s dotnet-sdk-6.0 2>/dev/null >/dev/null; 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
|
wget -nv https://packages.microsoft.com/config/ubuntu/22.04/packages-microsoft-prod.deb -O packages-microsoft-prod.deb
|
||||||
@@ -88,6 +127,15 @@ install() {
|
|||||||
fi
|
fi
|
||||||
continue
|
continue
|
||||||
fi
|
fi
|
||||||
|
if [ "$pkg" == openjdk-17-jdk-headless ]; then
|
||||||
|
if ! dpkg -s "$pkg" 2>/dev/null >/dev/null; then
|
||||||
|
apt install -y "$pkg"
|
||||||
|
# The default Java version should be Java 11
|
||||||
|
update-alternatives --set java /usr/lib/jvm/java-11-openjdk-amd64/bin/java
|
||||||
|
update-alternatives --set javac /usr/lib/jvm/java-11-openjdk-amd64/bin/javac
|
||||||
|
fi
|
||||||
|
continue
|
||||||
|
fi
|
||||||
apt install -y "$pkg"
|
apt install -y "$pkg"
|
||||||
done
|
done
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -415,6 +415,34 @@ if [ ! -f $PREFIX/bin/gdb ]; then
|
|||||||
--with-intel-pt \
|
--with-intel-pt \
|
||||||
--enable-tui \
|
--enable-tui \
|
||||||
--with-python=python3
|
--with-python=python3
|
||||||
|
elif [[ "${DISTRO}" == "amzn-2" ]]; then
|
||||||
|
# Remove readline, gdb does not compile
|
||||||
|
env \
|
||||||
|
CC=gcc \
|
||||||
|
CXX=g++ \
|
||||||
|
CFLAGS="-g -O2 -fstack-protector-strong -Wformat -Werror=format-security" \
|
||||||
|
CXXFLAGS="-g -O2 -fstack-protector-strong -Wformat -Werror=format-security" \
|
||||||
|
CPPFLAGS="-Wdate-time -D_FORTIFY_SOURCE=2 -fPIC" \
|
||||||
|
LDFLAGS="-Wl,-z,relro" \
|
||||||
|
PYTHON="" \
|
||||||
|
../configure \
|
||||||
|
--build=x86_64-linux-gnu \
|
||||||
|
--host=x86_64-linux-gnu \
|
||||||
|
--prefix=$PREFIX \
|
||||||
|
--disable-maintainer-mode \
|
||||||
|
--disable-dependency-tracking \
|
||||||
|
--disable-silent-rules \
|
||||||
|
--disable-gdbtk \
|
||||||
|
--disable-shared \
|
||||||
|
--without-guile \
|
||||||
|
--with-system-gdbinit=$PREFIX/etc/gdb/gdbinit \
|
||||||
|
--with-expat \
|
||||||
|
--with-system-zlib \
|
||||||
|
--with-lzma \
|
||||||
|
--with-babeltrace \
|
||||||
|
--with-intel-pt \
|
||||||
|
--enable-tui \
|
||||||
|
--with-python=python3
|
||||||
else
|
else
|
||||||
# https://buildd.debian.org/status/fetch.php?pkg=gdb&arch=amd64&ver=8.2.1-2&stamp=1550831554&raw=0
|
# https://buildd.debian.org/status/fetch.php?pkg=gdb&arch=amd64&ver=8.2.1-2&stamp=1550831554&raw=0
|
||||||
env \
|
env \
|
||||||
@@ -1143,119 +1171,121 @@ if [ ! -f $PREFIX/include/libaio.h ]; then
|
|||||||
popd
|
popd
|
||||||
fi
|
fi
|
||||||
|
|
||||||
log_tool_name "folly $FBLIBS_VERSION"
|
if [[ "${DISTRO}" != "amzn-2" ]]; then
|
||||||
if [ ! -d $PREFIX/include/folly ]; then
|
log_tool_name "folly $FBLIBS_VERSION"
|
||||||
if [ -d folly-$FBLIBS_VERSION ]; then
|
if [ ! -d $PREFIX/include/folly ]; then
|
||||||
rm -rf folly-$FBLIBS_VERSION
|
if [ -d folly-$FBLIBS_VERSION ]; then
|
||||||
|
rm -rf folly-$FBLIBS_VERSION
|
||||||
|
fi
|
||||||
|
mkdir folly-$FBLIBS_VERSION
|
||||||
|
tar -xzf ../archives/folly-$FBLIBS_VERSION.tar.gz -C folly-$FBLIBS_VERSION
|
||||||
|
pushd folly-$FBLIBS_VERSION
|
||||||
|
patch -p1 < ../../folly.patch
|
||||||
|
# build is used by facebook builder
|
||||||
|
mkdir _build
|
||||||
|
pushd _build
|
||||||
|
cmake .. $COMMON_CMAKE_FLAGS \
|
||||||
|
-DBOOST_LINK_STATIC=ON \
|
||||||
|
-DBUILD_TESTS=OFF \
|
||||||
|
-DGFLAGS_NOTHREADS=OFF \
|
||||||
|
-DCXX_STD="c++20"
|
||||||
|
make -j$CPUS install
|
||||||
|
popd && popd
|
||||||
fi
|
fi
|
||||||
mkdir folly-$FBLIBS_VERSION
|
|
||||||
tar -xzf ../archives/folly-$FBLIBS_VERSION.tar.gz -C folly-$FBLIBS_VERSION
|
|
||||||
pushd folly-$FBLIBS_VERSION
|
|
||||||
patch -p1 < ../../folly.patch
|
|
||||||
# build is used by facebook builder
|
|
||||||
mkdir _build
|
|
||||||
pushd _build
|
|
||||||
cmake .. $COMMON_CMAKE_FLAGS \
|
|
||||||
-DBOOST_LINK_STATIC=ON \
|
|
||||||
-DBUILD_TESTS=OFF \
|
|
||||||
-DGFLAGS_NOTHREADS=OFF \
|
|
||||||
-DCXX_STD="c++20"
|
|
||||||
make -j$CPUS install
|
|
||||||
popd && popd
|
|
||||||
fi
|
|
||||||
|
|
||||||
log_tool_name "fizz $FBLIBS_VERSION"
|
log_tool_name "fizz $FBLIBS_VERSION"
|
||||||
if [ ! -d $PREFIX/include/fizz ]; then
|
if [ ! -d $PREFIX/include/fizz ]; then
|
||||||
if [ -d fizz-$FBLIBS_VERSION ]; then
|
if [ -d fizz-$FBLIBS_VERSION ]; then
|
||||||
rm -rf fizz-$FBLIBS_VERSION
|
rm -rf fizz-$FBLIBS_VERSION
|
||||||
|
fi
|
||||||
|
mkdir fizz-$FBLIBS_VERSION
|
||||||
|
tar -xzf ../archives/fizz-$FBLIBS_VERSION.tar.gz -C fizz-$FBLIBS_VERSION
|
||||||
|
pushd fizz-$FBLIBS_VERSION
|
||||||
|
# build is used by facebook builder
|
||||||
|
mkdir _build
|
||||||
|
pushd _build
|
||||||
|
cmake ../fizz $COMMON_CMAKE_FLAGS \
|
||||||
|
-DBUILD_TESTS=OFF \
|
||||||
|
-DBUILD_EXAMPLES=OFF \
|
||||||
|
-DGFLAGS_NOTHREADS=OFF
|
||||||
|
make -j$CPUS install
|
||||||
|
popd && popd
|
||||||
fi
|
fi
|
||||||
mkdir fizz-$FBLIBS_VERSION
|
|
||||||
tar -xzf ../archives/fizz-$FBLIBS_VERSION.tar.gz -C fizz-$FBLIBS_VERSION
|
|
||||||
pushd fizz-$FBLIBS_VERSION
|
|
||||||
# build is used by facebook builder
|
|
||||||
mkdir _build
|
|
||||||
pushd _build
|
|
||||||
cmake ../fizz $COMMON_CMAKE_FLAGS \
|
|
||||||
-DBUILD_TESTS=OFF \
|
|
||||||
-DBUILD_EXAMPLES=OFF \
|
|
||||||
-DGFLAGS_NOTHREADS=OFF
|
|
||||||
make -j$CPUS install
|
|
||||||
popd && popd
|
|
||||||
fi
|
|
||||||
|
|
||||||
log_tool_name "wangle FBLIBS_VERSION"
|
log_tool_name "wangle FBLIBS_VERSION"
|
||||||
if [ ! -d $PREFIX/include/wangle ]; then
|
if [ ! -d $PREFIX/include/wangle ]; then
|
||||||
if [ -d wangle-$FBLIBS_VERSION ]; then
|
if [ -d wangle-$FBLIBS_VERSION ]; then
|
||||||
rm -rf wangle-$FBLIBS_VERSION
|
rm -rf wangle-$FBLIBS_VERSION
|
||||||
|
fi
|
||||||
|
mkdir wangle-$FBLIBS_VERSION
|
||||||
|
tar -xzf ../archives/wangle-$FBLIBS_VERSION.tar.gz -C wangle-$FBLIBS_VERSION
|
||||||
|
pushd wangle-$FBLIBS_VERSION
|
||||||
|
# build is used by facebook builder
|
||||||
|
mkdir _build
|
||||||
|
pushd _build
|
||||||
|
cmake ../wangle $COMMON_CMAKE_FLAGS \
|
||||||
|
-DBUILD_TESTS=OFF \
|
||||||
|
-DBUILD_EXAMPLES=OFF \
|
||||||
|
-DGFLAGS_NOTHREADS=OFF
|
||||||
|
make -j$CPUS install
|
||||||
|
popd && popd
|
||||||
fi
|
fi
|
||||||
mkdir wangle-$FBLIBS_VERSION
|
|
||||||
tar -xzf ../archives/wangle-$FBLIBS_VERSION.tar.gz -C wangle-$FBLIBS_VERSION
|
|
||||||
pushd wangle-$FBLIBS_VERSION
|
|
||||||
# build is used by facebook builder
|
|
||||||
mkdir _build
|
|
||||||
pushd _build
|
|
||||||
cmake ../wangle $COMMON_CMAKE_FLAGS \
|
|
||||||
-DBUILD_TESTS=OFF \
|
|
||||||
-DBUILD_EXAMPLES=OFF \
|
|
||||||
-DGFLAGS_NOTHREADS=OFF
|
|
||||||
make -j$CPUS install
|
|
||||||
popd && popd
|
|
||||||
fi
|
|
||||||
|
|
||||||
log_tool_name "proxygen $FBLIBS_VERSION"
|
log_tool_name "proxygen $FBLIBS_VERSION"
|
||||||
if [ ! -d $PREFIX/include/proxygen ]; then
|
if [ ! -d $PREFIX/include/proxygen ]; then
|
||||||
if [ -d proxygen-$FBLIBS_VERSION ]; then
|
if [ -d proxygen-$FBLIBS_VERSION ]; then
|
||||||
rm -rf proxygen-$FBLIBS_VERSION
|
rm -rf proxygen-$FBLIBS_VERSION
|
||||||
|
fi
|
||||||
|
mkdir proxygen-$FBLIBS_VERSION
|
||||||
|
tar -xzf ../archives/proxygen-$FBLIBS_VERSION.tar.gz -C proxygen-$FBLIBS_VERSION
|
||||||
|
pushd proxygen-$FBLIBS_VERSION
|
||||||
|
patch -p1 < ../../proxygen.patch
|
||||||
|
# build is used by facebook builder
|
||||||
|
mkdir _build
|
||||||
|
pushd _build
|
||||||
|
cmake .. $COMMON_CMAKE_FLAGS \
|
||||||
|
-DBUILD_TESTS=OFF \
|
||||||
|
-DBUILD_SAMPLES=OFF \
|
||||||
|
-DGFLAGS_NOTHREADS=OFF \
|
||||||
|
-DBUILD_QUIC=OFF
|
||||||
|
make -j$CPUS install
|
||||||
|
popd && popd
|
||||||
fi
|
fi
|
||||||
mkdir proxygen-$FBLIBS_VERSION
|
|
||||||
tar -xzf ../archives/proxygen-$FBLIBS_VERSION.tar.gz -C proxygen-$FBLIBS_VERSION
|
|
||||||
pushd proxygen-$FBLIBS_VERSION
|
|
||||||
patch -p1 < ../../proxygen.patch
|
|
||||||
# build is used by facebook builder
|
|
||||||
mkdir _build
|
|
||||||
pushd _build
|
|
||||||
cmake .. $COMMON_CMAKE_FLAGS \
|
|
||||||
-DBUILD_TESTS=OFF \
|
|
||||||
-DBUILD_SAMPLES=OFF \
|
|
||||||
-DGFLAGS_NOTHREADS=OFF \
|
|
||||||
-DBUILD_QUIC=OFF
|
|
||||||
make -j$CPUS install
|
|
||||||
popd && popd
|
|
||||||
fi
|
|
||||||
|
|
||||||
log_tool_name "flex $FBLIBS_VERSION"
|
log_tool_name "flex $FBLIBS_VERSION"
|
||||||
if [ ! -f $PREFIX/include/FlexLexer.h ]; then
|
if [ ! -f $PREFIX/include/FlexLexer.h ]; then
|
||||||
if [ -d flex-$FLEX_VERSION ]; then
|
if [ -d flex-$FLEX_VERSION ]; then
|
||||||
rm -rf flex-$FLEX_VERSION
|
rm -rf flex-$FLEX_VERSION
|
||||||
|
fi
|
||||||
|
tar -xzf ../archives/flex-$FLEX_VERSION.tar.gz
|
||||||
|
pushd flex-$FLEX_VERSION
|
||||||
|
./configure $COMMON_CONFIGURE_FLAGS
|
||||||
|
make -j$CPUS install
|
||||||
|
popd
|
||||||
fi
|
fi
|
||||||
tar -xzf ../archives/flex-$FLEX_VERSION.tar.gz
|
|
||||||
pushd flex-$FLEX_VERSION
|
|
||||||
./configure $COMMON_CONFIGURE_FLAGS
|
|
||||||
make -j$CPUS install
|
|
||||||
popd
|
|
||||||
fi
|
|
||||||
|
|
||||||
log_tool_name "fbthrift $FBLIBS_VERSION"
|
log_tool_name "fbthrift $FBLIBS_VERSION"
|
||||||
if [ ! -d $PREFIX/include/thrift ]; then
|
if [ ! -d $PREFIX/include/thrift ]; then
|
||||||
if [ -d fbthrift-$FBLIBS_VERSION ]; then
|
if [ -d fbthrift-$FBLIBS_VERSION ]; then
|
||||||
rm -rf fbthrift-$FBLIBS_VERSION
|
rm -rf fbthrift-$FBLIBS_VERSION
|
||||||
|
fi
|
||||||
|
git clone --depth 1 --branch v$FBLIBS_VERSION https://github.com/facebook/fbthrift.git fbthrift-$FBLIBS_VERSION
|
||||||
|
pushd fbthrift-$FBLIBS_VERSION
|
||||||
|
# build is used by facebook builder
|
||||||
|
mkdir _build
|
||||||
|
pushd _build
|
||||||
|
if [ "$TOOLCHAIN_STDCXX" = "libstdc++" ]; then
|
||||||
|
CMAKE_CXX_FLAGS="-fsized-deallocation"
|
||||||
|
else
|
||||||
|
CMAKE_CXX_FLAGS="-fsized-deallocation -stdlib=libc++"
|
||||||
|
fi
|
||||||
|
cmake .. $COMMON_CMAKE_FLAGS \
|
||||||
|
-Denable_tests=OFF \
|
||||||
|
-DGFLAGS_NOTHREADS=OFF \
|
||||||
|
-DCMAKE_CXX_FLAGS="$CMAKE_CXX_FLAGS"
|
||||||
|
make -j$CPUS install
|
||||||
|
popd
|
||||||
fi
|
fi
|
||||||
git clone --depth 1 --branch v$FBLIBS_VERSION https://github.com/facebook/fbthrift.git fbthrift-$FBLIBS_VERSION
|
|
||||||
pushd fbthrift-$FBLIBS_VERSION
|
|
||||||
# build is used by facebook builder
|
|
||||||
mkdir _build
|
|
||||||
pushd _build
|
|
||||||
if [ "$TOOLCHAIN_STDCXX" = "libstdc++" ]; then
|
|
||||||
CMAKE_CXX_FLAGS="-fsized-deallocation"
|
|
||||||
else
|
|
||||||
CMAKE_CXX_FLAGS="-fsized-deallocation -stdlib=libc++"
|
|
||||||
fi
|
|
||||||
cmake .. $COMMON_CMAKE_FLAGS \
|
|
||||||
-Denable_tests=OFF \
|
|
||||||
-DGFLAGS_NOTHREADS=OFF \
|
|
||||||
-DCMAKE_CXX_FLAGS="$CMAKE_CXX_FLAGS"
|
|
||||||
make -j$CPUS install
|
|
||||||
popd
|
|
||||||
fi
|
fi
|
||||||
|
|
||||||
popd
|
popd
|
||||||
|
|||||||
@@ -1,8 +1,15 @@
|
|||||||
#!/bin/bash
|
#!/bin/bash
|
||||||
|
|
||||||
function operating_system() {
|
function operating_system() {
|
||||||
grep -E '^(VERSION_)?ID=' /etc/os-release | \
|
if [[ "$OSTYPE" == "linux-gnu"* ]]; then
|
||||||
sort | cut -d '=' -f 2- | sed 's/"//g' | paste -s -d '-'
|
grep -E '^(VERSION_)?ID=' /etc/os-release | \
|
||||||
|
sort | cut -d '=' -f 2- | sed 's/"//g' | paste -s -d '-'
|
||||||
|
elif [[ "$OSTYPE" == "darwin"* ]]; then
|
||||||
|
echo "$(sw_vers -productName)-$(sw_vers -productVersion | cut -d '.' -f 1)"
|
||||||
|
else
|
||||||
|
echo "operating_system called on an unknown OS"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
}
|
}
|
||||||
|
|
||||||
function check_operating_system() {
|
function check_operating_system() {
|
||||||
@@ -76,3 +83,28 @@ function install_all_apt() {
|
|||||||
apt install -y "$pkg"
|
apt install -y "$pkg"
|
||||||
done
|
done
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function install_custom_golang() {
|
||||||
|
# NOTE: The official https://go.dev/doc/manage-install doesn't seem to be working.
|
||||||
|
GOVERSION="$1"
|
||||||
|
GOINSTALLDIR="/opt/go$GOVERSION"
|
||||||
|
GOROOT="$GOINSTALLDIR/go" # GOPATH=$HOME/go
|
||||||
|
if [ ! -f "$GOROOT/bin/go" ]; then
|
||||||
|
curl -LO https://go.dev/dl/go$GOVERSION.linux-amd64.tar.gz
|
||||||
|
mkdir -p "$GOINSTALLDIR"
|
||||||
|
tar -C "$GOINSTALLDIR" -xzf go$GOVERSION.linux-amd64.tar.gz
|
||||||
|
fi
|
||||||
|
echo "go $GOVERSION installed under $GOROOT"
|
||||||
|
}
|
||||||
|
|
||||||
|
function install_custom_maven() {
|
||||||
|
MVNVERSION="$1"
|
||||||
|
MVNINSTALLDIR="/opt/apache-maven-$MVNVERSION"
|
||||||
|
MVNURL="https://s3.eu-west-1.amazonaws.com/deps.memgraph.io/maven/apache-maven-$MVNVERSION-bin.tar.gz"
|
||||||
|
if [ ! -f "$MVNINSTALLDIR/bin/mvn" ]; then
|
||||||
|
echo "Downloading maven from $MVNURL"
|
||||||
|
curl -LO "$MVNURL"
|
||||||
|
tar -C "/opt" -xzf "apache-maven-$MVNVERSION-bin.tar.gz"
|
||||||
|
fi
|
||||||
|
echo "maven $MVNVERSION installed under $MVNINSTALLDIR"
|
||||||
|
}
|
||||||
|
|||||||
26
import/mglogs2cypherl.sh
Executable file
26
import/mglogs2cypherl.sh
Executable file
@@ -0,0 +1,26 @@
|
|||||||
|
#!/bin/bash -e
|
||||||
|
COLOR_ORANGE="\e[38;5;208m"
|
||||||
|
COLOR_GREEN="\e[38;5;35m"
|
||||||
|
COLOR_RED="\e[0;31m"
|
||||||
|
COLOR_NULL="\e[0m"
|
||||||
|
|
||||||
|
print_help() {
|
||||||
|
echo -e "${COLOR_ORANGE}HOW TO RUN:${COLOR_NULL} $0 memgraph_logs_file_path cypherl_output_path"
|
||||||
|
exit 1
|
||||||
|
}
|
||||||
|
|
||||||
|
if [ "$#" -ne 2 ]; then
|
||||||
|
print_help
|
||||||
|
fi
|
||||||
|
INPUT="$1"
|
||||||
|
OUTPUT="$2"
|
||||||
|
if [ ! -f "$INPUT" ]; then
|
||||||
|
echo -e "${COLOR_RED}ERROR:${COLOR_NULL} memgraph_logs_file_path is not a file!"
|
||||||
|
print_help
|
||||||
|
fi
|
||||||
|
|
||||||
|
awk -v RS="Run] '" 'NR>1 { print $0 }' < "$INPUT" | sed -e "/^\[/d;" -e "s/'\([^']*\)$/;/g" > "$OUTPUT"
|
||||||
|
|
||||||
|
echo -e "${COLOR_GREEN}DONE!${COLOR_NULL} Please find Memgraph compatible cypherl file under $OUTPUT"
|
||||||
|
echo ""
|
||||||
|
echo "Import can be done by executing => \`cat $OUTPUT | mgconsole\`"
|
||||||
35
import/n2mg_cypherl.sh
Executable file
35
import/n2mg_cypherl.sh
Executable file
@@ -0,0 +1,35 @@
|
|||||||
|
#!/bin/bash -e
|
||||||
|
COLOR_ORANGE="\e[38;5;208m"
|
||||||
|
COLOR_GREEN="\e[38;5;35m"
|
||||||
|
COLOR_RED="\e[0;31m"
|
||||||
|
COLOR_NULL="\e[0m"
|
||||||
|
|
||||||
|
print_help() {
|
||||||
|
echo -e "${COLOR_ORANGE}HOW TO RUN:${COLOR_NULL} $0 input_file_path output_file_path"
|
||||||
|
exit 1
|
||||||
|
}
|
||||||
|
|
||||||
|
if [ "$#" -ne 2 ]; then
|
||||||
|
print_help
|
||||||
|
fi
|
||||||
|
INPUT="$1"
|
||||||
|
OUTPUT="$2"
|
||||||
|
if [ ! -f "$INPUT" ]; then
|
||||||
|
echo -e "${COLOR_RED}ERROR:${COLOR_NULL} input_file_path is not a file!"
|
||||||
|
print_help
|
||||||
|
fi
|
||||||
|
|
||||||
|
echo -e "${COLOR_ORANGE}NOTE:${COLOR_NULL} BEGIN and COMMIT are required because variables share the same name (e.g. row)"
|
||||||
|
echo -e "${COLOR_ORANGE}NOTE:${COLOR_NULL} CONSTRAINTS are just skipped -> ${COLOR_RED}please create consraints manually if needed${COLOR_NULL}"
|
||||||
|
|
||||||
|
sed -e 's/^:begin/BEGIN/g; s/^BEGIN$/BEGIN;/g;' \
|
||||||
|
-e 's/^:commit/COMMIT/g; s/^COMMIT$/COMMIT;/g;' \
|
||||||
|
-e '/^CALL/d; /^SCHEMA AWAIT/d;' \
|
||||||
|
-e 's/CREATE RANGE INDEX FOR (n:/CREATE INDEX ON :/g;' \
|
||||||
|
-e 's/) ON (n./(/g;' \
|
||||||
|
-e '/^CREATE CONSTRAINT/d; /^DROP CONSTRAINT/d;' "$INPUT" > "$OUTPUT"
|
||||||
|
|
||||||
|
echo ""
|
||||||
|
echo -e "${COLOR_GREEN}DONE!${COLOR_NULL} Please find Memgraph compatible cypherl|.cypher file under $OUTPUT"
|
||||||
|
echo ""
|
||||||
|
echo "Please import data by executing => \`cat $OUTPUT | mgconsole\`"
|
||||||
@@ -135,6 +135,13 @@ inline int64_t value_get_int(mgp_value *val) { return MgInvoke<int64_t>(mgp_valu
|
|||||||
|
|
||||||
inline double value_get_double(mgp_value *val) { return MgInvoke<double>(mgp_value_get_double, val); }
|
inline double value_get_double(mgp_value *val) { return MgInvoke<double>(mgp_value_get_double, val); }
|
||||||
|
|
||||||
|
inline double value_get_numeric(mgp_value *val) {
|
||||||
|
if (MgInvoke<int>(mgp_value_is_int, val)) {
|
||||||
|
return static_cast<double>(value_get_int(val));
|
||||||
|
}
|
||||||
|
return value_get_double(val);
|
||||||
|
}
|
||||||
|
|
||||||
inline const char *value_get_string(mgp_value *val) { return MgInvoke<const char *>(mgp_value_get_string, val); }
|
inline const char *value_get_string(mgp_value *val) { return MgInvoke<const char *>(mgp_value_get_string, val); }
|
||||||
|
|
||||||
inline mgp_list *value_get_list(mgp_value *val) { return MgInvoke<mgp_list *>(mgp_value_get_list, val); }
|
inline mgp_list *value_get_list(mgp_value *val) { return MgInvoke<mgp_list *>(mgp_value_get_list, val); }
|
||||||
@@ -171,6 +178,8 @@ inline bool value_is_int(mgp_value *val) { return MgInvoke<int>(mgp_value_is_int
|
|||||||
|
|
||||||
inline bool value_is_double(mgp_value *val) { return MgInvoke<int>(mgp_value_is_double, val); }
|
inline bool value_is_double(mgp_value *val) { return MgInvoke<int>(mgp_value_is_double, val); }
|
||||||
|
|
||||||
|
inline bool value_is_numeric(mgp_value *val) { return value_is_int(val) || value_is_double(val); }
|
||||||
|
|
||||||
inline bool value_is_string(mgp_value *val) { return MgInvoke<int>(mgp_value_is_string, val); }
|
inline bool value_is_string(mgp_value *val) { return MgInvoke<int>(mgp_value_is_string, val); }
|
||||||
|
|
||||||
inline bool value_is_list(mgp_value *val) { return MgInvoke<int>(mgp_value_is_list, val); }
|
inline bool value_is_list(mgp_value *val) { return MgInvoke<int>(mgp_value_is_list, val); }
|
||||||
@@ -246,6 +255,16 @@ inline mgp_edge *graph_create_edge(mgp_graph *graph, mgp_vertex *from, mgp_verte
|
|||||||
return MgInvoke<mgp_edge *>(mgp_graph_create_edge, graph, from, to, type, memory);
|
return MgInvoke<mgp_edge *>(mgp_graph_create_edge, graph, from, to, type, memory);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
inline mgp_edge *graph_edge_set_from(struct mgp_graph *graph, struct mgp_edge *e, struct mgp_vertex *new_from,
|
||||||
|
mgp_memory *memory) {
|
||||||
|
return MgInvoke<mgp_edge *>(mgp_graph_edge_set_from, graph, e, new_from, memory);
|
||||||
|
}
|
||||||
|
|
||||||
|
inline mgp_edge *graph_edge_set_to(struct mgp_graph *graph, struct mgp_edge *e, struct mgp_vertex *new_to,
|
||||||
|
mgp_memory *memory) {
|
||||||
|
return MgInvoke<mgp_edge *>(mgp_graph_edge_set_to, graph, e, new_to, memory);
|
||||||
|
}
|
||||||
|
|
||||||
inline void graph_delete_edge(mgp_graph *graph, mgp_edge *edge) { MgInvokeVoid(mgp_graph_delete_edge, graph, edge); }
|
inline void graph_delete_edge(mgp_graph *graph, mgp_edge *edge) { MgInvokeVoid(mgp_graph_delete_edge, graph, edge); }
|
||||||
|
|
||||||
inline mgp_vertex *graph_get_vertex_by_id(mgp_graph *g, mgp_vertex_id id, mgp_memory *memory) {
|
inline mgp_vertex *graph_get_vertex_by_id(mgp_graph *g, mgp_vertex_id id, mgp_memory *memory) {
|
||||||
@@ -326,6 +345,12 @@ inline void map_insert(mgp_map *map, const char *key, mgp_value *value) {
|
|||||||
MgInvokeVoid(mgp_map_insert, map, key, value);
|
MgInvokeVoid(mgp_map_insert, map, key, value);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
inline void map_update(mgp_map *map, const char *key, mgp_value *value) {
|
||||||
|
MgInvokeVoid(mgp_map_update, map, key, value);
|
||||||
|
}
|
||||||
|
|
||||||
|
inline void map_erase(mgp_map *map, const char *key) { MgInvokeVoid(mgp_map_erase, map, key); }
|
||||||
|
|
||||||
inline size_t map_size(mgp_map *map) { return MgInvoke<size_t>(mgp_map_size, map); }
|
inline size_t map_size(mgp_map *map) { return MgInvoke<size_t>(mgp_map_size, map); }
|
||||||
|
|
||||||
inline mgp_value *map_at(mgp_map *map, const char *key) { return MgInvoke<mgp_value *>(mgp_map_at, map, key); }
|
inline mgp_value *map_at(mgp_map *map, const char *key) { return MgInvoke<mgp_value *>(mgp_map_at, map, key); }
|
||||||
@@ -352,6 +377,10 @@ inline mgp_map_item *map_items_iterator_next(mgp_map_items_iterator *it) {
|
|||||||
|
|
||||||
inline mgp_vertex_id vertex_get_id(mgp_vertex *v) { return MgInvoke<mgp_vertex_id>(mgp_vertex_get_id, v); }
|
inline mgp_vertex_id vertex_get_id(mgp_vertex *v) { return MgInvoke<mgp_vertex_id>(mgp_vertex_get_id, v); }
|
||||||
|
|
||||||
|
inline size_t vertex_get_in_degree(mgp_vertex *v) { return MgInvoke<size_t>(mgp_vertex_get_in_degree, v); }
|
||||||
|
|
||||||
|
inline size_t vertex_get_out_degree(mgp_vertex *v) { return MgInvoke<size_t>(mgp_vertex_get_out_degree, v); }
|
||||||
|
|
||||||
inline mgp_vertex *vertex_copy(mgp_vertex *v, mgp_memory *memory) {
|
inline mgp_vertex *vertex_copy(mgp_vertex *v, mgp_memory *memory) {
|
||||||
return MgInvoke<mgp_vertex *>(mgp_vertex_copy, v, memory);
|
return MgInvoke<mgp_vertex *>(mgp_vertex_copy, v, memory);
|
||||||
}
|
}
|
||||||
@@ -374,6 +403,10 @@ inline bool vertex_has_label_named(mgp_vertex *v, const char *label_name) {
|
|||||||
|
|
||||||
inline void vertex_add_label(mgp_vertex *vertex, mgp_label label) { MgInvokeVoid(mgp_vertex_add_label, vertex, label); }
|
inline void vertex_add_label(mgp_vertex *vertex, mgp_label label) { MgInvokeVoid(mgp_vertex_add_label, vertex, label); }
|
||||||
|
|
||||||
|
inline void vertex_remove_label(mgp_vertex *vertex, mgp_label label) {
|
||||||
|
MgInvokeVoid(mgp_vertex_remove_label, vertex, label);
|
||||||
|
}
|
||||||
|
|
||||||
inline mgp_value *vertex_get_property(mgp_vertex *v, const char *property_name, mgp_memory *memory) {
|
inline mgp_value *vertex_get_property(mgp_vertex *v, const char *property_name, mgp_memory *memory) {
|
||||||
return MgInvoke<mgp_value *>(mgp_vertex_get_property, v, property_name, memory);
|
return MgInvoke<mgp_value *>(mgp_vertex_get_property, v, property_name, memory);
|
||||||
}
|
}
|
||||||
@@ -382,6 +415,10 @@ inline void vertex_set_property(mgp_vertex *v, const char *property_name, mgp_va
|
|||||||
MgInvokeVoid(mgp_vertex_set_property, v, property_name, property_value);
|
MgInvokeVoid(mgp_vertex_set_property, v, property_name, property_value);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
inline void vertex_set_properties(mgp_vertex *v, struct mgp_map *properties) {
|
||||||
|
MgInvokeVoid(mgp_vertex_set_properties, v, properties);
|
||||||
|
}
|
||||||
|
|
||||||
inline mgp_properties_iterator *vertex_iter_properties(mgp_vertex *v, mgp_memory *memory) {
|
inline mgp_properties_iterator *vertex_iter_properties(mgp_vertex *v, mgp_memory *memory) {
|
||||||
return MgInvoke<mgp_properties_iterator *>(mgp_vertex_iter_properties, v, memory);
|
return MgInvoke<mgp_properties_iterator *>(mgp_vertex_iter_properties, v, memory);
|
||||||
}
|
}
|
||||||
@@ -418,6 +455,10 @@ inline void edge_set_property(mgp_edge *e, const char *property_name, mgp_value
|
|||||||
MgInvokeVoid(mgp_edge_set_property, e, property_name, property_value);
|
MgInvokeVoid(mgp_edge_set_property, e, property_name, property_value);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
inline void edge_set_properties(mgp_edge *e, struct mgp_map *properties) {
|
||||||
|
MgInvokeVoid(mgp_edge_set_properties, e, properties);
|
||||||
|
}
|
||||||
|
|
||||||
inline mgp_properties_iterator *edge_iter_properties(mgp_edge *e, mgp_memory *memory) {
|
inline mgp_properties_iterator *edge_iter_properties(mgp_edge *e, mgp_memory *memory) {
|
||||||
return MgInvoke<mgp_properties_iterator *>(mgp_edge_iter_properties, e, memory);
|
return MgInvoke<mgp_properties_iterator *>(mgp_edge_iter_properties, e, memory);
|
||||||
}
|
}
|
||||||
@@ -677,6 +718,16 @@ inline mgp_proc *module_add_write_procedure(mgp_module *module, const char *name
|
|||||||
return MgInvoke<mgp_proc *>(mgp_module_add_write_procedure, module, name, cb);
|
return MgInvoke<mgp_proc *>(mgp_module_add_write_procedure, module, name, cb);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
inline mgp_proc *module_add_batch_read_procedure(mgp_module *module, const char *name, mgp_proc_cb cb,
|
||||||
|
mgp_proc_initializer initializer, mgp_proc_cleanup cleanup) {
|
||||||
|
return MgInvoke<mgp_proc *>(mgp_module_add_batch_read_procedure, module, name, cb, initializer, cleanup);
|
||||||
|
}
|
||||||
|
|
||||||
|
inline mgp_proc *module_add_batch_write_procedure(mgp_module *module, const char *name, mgp_proc_cb cb,
|
||||||
|
mgp_proc_initializer initializer, mgp_proc_cleanup cleanup) {
|
||||||
|
return MgInvoke<mgp_proc *>(mgp_module_add_batch_write_procedure, module, name, cb, initializer, cleanup);
|
||||||
|
}
|
||||||
|
|
||||||
inline void proc_add_arg(mgp_proc *proc, const char *name, mgp_type *type) {
|
inline void proc_add_arg(mgp_proc *proc, const char *name, mgp_type *type) {
|
||||||
MgInvokeVoid(mgp_proc_add_arg, proc, name, type);
|
MgInvokeVoid(mgp_proc_add_arg, proc, name, type);
|
||||||
}
|
}
|
||||||
@@ -693,7 +744,7 @@ inline void proc_add_deprecated_result(mgp_proc *proc, const char *name, mgp_typ
|
|||||||
MgInvokeVoid(mgp_proc_add_deprecated_result, proc, name, type);
|
MgInvokeVoid(mgp_proc_add_deprecated_result, proc, name, type);
|
||||||
}
|
}
|
||||||
|
|
||||||
inline bool must_abort(mgp_graph *graph) { return mgp_must_abort(graph); }
|
inline int must_abort(mgp_graph *graph) { return mgp_must_abort(graph); }
|
||||||
|
|
||||||
// mgp_result
|
// mgp_result
|
||||||
|
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
// Copyright 2022 Memgraph Ltd.
|
// Copyright 2023 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,45 +13,96 @@
|
|||||||
|
|
||||||
#include <exception>
|
#include <exception>
|
||||||
#include <iostream>
|
#include <iostream>
|
||||||
|
#include <sstream>
|
||||||
|
#include <string>
|
||||||
|
|
||||||
namespace mg_exception {
|
namespace mg_exception {
|
||||||
struct NotEnoughMemoryException : public std::exception {
|
|
||||||
const char *what() const throw() { return "Not enough memory!"; }
|
// Instead of writing this utility function, we could have used `fmt::format`, but that's not an ideal option here
|
||||||
};
|
// because that would introduce dependency that would be propagated to the client code (if exceptions here would be
|
||||||
|
// used). Since the functionality here is not complex + the code is not on a critical path, we opted for a pure C++
|
||||||
|
// solution.
|
||||||
|
template <typename FirstArg, typename... Args>
|
||||||
|
std::string StringSerialize(FirstArg &&firstArg, Args &&...args) {
|
||||||
|
std::stringstream stream;
|
||||||
|
stream << firstArg;
|
||||||
|
((stream << " " << args), ...);
|
||||||
|
return stream.str();
|
||||||
|
}
|
||||||
|
|
||||||
struct UnknownException : public std::exception {
|
struct UnknownException : public std::exception {
|
||||||
const char *what() const throw() { return "Unknown exception!"; }
|
const char *what() const noexcept override { return "Unknown exception!"; }
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct NotEnoughMemoryException : public std::exception {
|
||||||
|
NotEnoughMemoryException()
|
||||||
|
: message_{
|
||||||
|
StringSerialize("Not enough memory! For more details please visit", "https://memgr.ph/memory-control")} {}
|
||||||
|
const char *what() const noexcept override { return message_.c_str(); }
|
||||||
|
|
||||||
|
private:
|
||||||
|
std::string message_;
|
||||||
|
};
|
||||||
|
|
||||||
struct AllocationException : public std::exception {
|
struct AllocationException : public std::exception {
|
||||||
const char *what() const throw() { return "Could not allocate memory!"; }
|
AllocationException()
|
||||||
|
: message_{StringSerialize("Could not allocate memory. For more details please visit",
|
||||||
|
"https://memgr.ph/memory-control")} {}
|
||||||
|
const char *what() const noexcept override { return message_.c_str(); }
|
||||||
|
|
||||||
|
private:
|
||||||
|
std::string message_;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct InsufficientBufferException : public std::exception {
|
struct InsufficientBufferException : public std::exception {
|
||||||
const char *what() const throw() { return "Buffer is not sufficient to process procedure!"; }
|
const char *what() const noexcept override { return "Buffer is not sufficient to process procedure!"; }
|
||||||
};
|
};
|
||||||
|
|
||||||
struct OutOfRangeException : public std::exception {
|
struct OutOfRangeException : public std::exception {
|
||||||
const char *what() const throw() { return "Index out of range!"; }
|
const char *what() const noexcept override { return "Index out of range!"; }
|
||||||
};
|
};
|
||||||
|
|
||||||
struct LogicException : public std::exception {
|
struct LogicException : public std::exception {
|
||||||
const char *what() const throw() { return "Logic exception, check the procedure signature!"; }
|
const char *what() const noexcept override { return "Logic exception, check the procedure signature!"; }
|
||||||
};
|
};
|
||||||
|
|
||||||
struct DeletedObjectException : public std::exception {
|
struct DeletedObjectException : public std::exception {
|
||||||
const char *what() const throw() { return "Object is deleted!"; }
|
const char *what() const noexcept override { return "Object is deleted!"; }
|
||||||
};
|
};
|
||||||
|
|
||||||
struct InvalidArgumentException : public std::exception {
|
struct InvalidArgumentException : public std::exception {
|
||||||
const char *what() const throw() { return "Invalid argument!"; }
|
const char *what() const noexcept override { return "Invalid argument!"; }
|
||||||
};
|
};
|
||||||
|
|
||||||
struct InvalidIDException : public std::exception {
|
struct InvalidIDException : public std::exception {
|
||||||
const char *what() const throw() { return "Invalid ID!"; }
|
InvalidIDException() : message_{"Invalid ID!"} {}
|
||||||
|
explicit InvalidIDException(std::uint64_t identifier) : message_{StringSerialize("Invalid ID =", identifier)} {}
|
||||||
|
const char *what() const noexcept override { return message_.c_str(); }
|
||||||
|
|
||||||
|
private:
|
||||||
|
std::string message_;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct KeyAlreadyExistsException : public std::exception {
|
struct KeyAlreadyExistsException : public std::exception {
|
||||||
const char *what() const throw() { return "Key you are trying to set already exists!"; }
|
KeyAlreadyExistsException() : message_{"Key you are trying to set already exists!"} {}
|
||||||
|
explicit KeyAlreadyExistsException(const std::string &key)
|
||||||
|
: message_{StringSerialize("Key you are trying to set already exists! KEY = ", key)} {}
|
||||||
|
const char *what() const noexcept override { return message_.c_str(); }
|
||||||
|
|
||||||
|
private:
|
||||||
|
std::string message_;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct ImmutableObjectException : public std::exception {
|
struct ImmutableObjectException : public std::exception {
|
||||||
const char *what() const throw() { return "Object you are trying to change is immutable!"; }
|
const char *what() const noexcept override { return "Object you are trying to change is immutable!"; }
|
||||||
};
|
};
|
||||||
|
|
||||||
struct ValueConversionException : public std::exception {
|
struct ValueConversionException : public std::exception {
|
||||||
const char *what() const throw() { return "Error in value conversion!"; }
|
const char *what() const noexcept override { return "Error in value conversion!"; }
|
||||||
};
|
};
|
||||||
|
|
||||||
struct SerializationException : public std::exception {
|
struct SerializationException : public std::exception {
|
||||||
const char *what() const throw() { return "Error in serialization!"; }
|
const char *what() const noexcept override { return "Error in serialization!"; }
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace mg_exception
|
} // namespace mg_exception
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
// Copyright 2022 Memgraph Ltd.
|
// Copyright 2023 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
|
||||||
@@ -462,6 +462,18 @@ void mgp_map_destroy(struct mgp_map *map);
|
|||||||
/// Return mgp_error::MGP_ERROR_KEY_ALREADY_EXISTS if a previous mapping already exists.
|
/// Return mgp_error::MGP_ERROR_KEY_ALREADY_EXISTS if a previous mapping already exists.
|
||||||
enum mgp_error mgp_map_insert(struct mgp_map *map, const char *key, struct mgp_value *value);
|
enum mgp_error mgp_map_insert(struct mgp_map *map, const char *key, struct mgp_value *value);
|
||||||
|
|
||||||
|
/// Insert a mapping from a NULL terminated character string to a value.
|
||||||
|
/// If a mapping with the same key already exists, it is replaced.
|
||||||
|
/// In case of update, both the string and the value are copied into the map.
|
||||||
|
/// Therefore, the map does not take ownership of the original key nor value, so
|
||||||
|
/// you still need to free their memory explicitly.
|
||||||
|
/// Return mgp_error::MGP_ERROR_UNABLE_TO_ALLOCATE is returned if unable to allocate for insertion.
|
||||||
|
enum mgp_error mgp_map_update(struct mgp_map *map, const char *key, struct mgp_value *value);
|
||||||
|
|
||||||
|
// Erase a mapping by key.
|
||||||
|
// If the key doesn't exist in the map nothing happens
|
||||||
|
enum mgp_error mgp_map_erase(struct mgp_map *map, const char *key);
|
||||||
|
|
||||||
/// Get the number of items stored in mgp_map.
|
/// Get the number of items stored in mgp_map.
|
||||||
/// Current implementation always returns without errors.
|
/// Current implementation always returns without errors.
|
||||||
enum mgp_error mgp_map_size(struct mgp_map *map, size_t *result);
|
enum mgp_error mgp_map_size(struct mgp_map *map, size_t *result);
|
||||||
@@ -635,6 +647,12 @@ struct mgp_vertex_id {
|
|||||||
/// Get the ID of given vertex.
|
/// Get the ID of given vertex.
|
||||||
enum mgp_error mgp_vertex_get_id(struct mgp_vertex *v, struct mgp_vertex_id *result);
|
enum mgp_error mgp_vertex_get_id(struct mgp_vertex *v, struct mgp_vertex_id *result);
|
||||||
|
|
||||||
|
/// Get the in degree of given vertex.
|
||||||
|
enum mgp_error mgp_vertex_get_in_degree(struct mgp_vertex *v, size_t *result);
|
||||||
|
|
||||||
|
/// Get the out degree of given vertex.
|
||||||
|
enum mgp_error mgp_vertex_get_out_degree(struct mgp_vertex *v, size_t *result);
|
||||||
|
|
||||||
/// Result is non-zero if the vertex can be modified.
|
/// Result is non-zero if the vertex can be modified.
|
||||||
/// The mutability of the vertex is the same as the graph which it is part of. If a vertex is immutable, then edges
|
/// The mutability of the vertex is the same as the graph which it is part of. If a vertex is immutable, then edges
|
||||||
/// cannot be created or deleted, properties and labels cannot be set or removed and all of the returned edges will be
|
/// cannot be created or deleted, properties and labels cannot be set or removed and all of the returned edges will be
|
||||||
@@ -652,6 +670,15 @@ enum mgp_error mgp_vertex_underlying_graph_is_mutable(struct mgp_vertex *v, int
|
|||||||
enum mgp_error mgp_vertex_set_property(struct mgp_vertex *v, const char *property_name,
|
enum mgp_error mgp_vertex_set_property(struct mgp_vertex *v, const char *property_name,
|
||||||
struct mgp_value *property_value);
|
struct mgp_value *property_value);
|
||||||
|
|
||||||
|
/// Set the value of properties on a vertex.
|
||||||
|
/// When the value is `null`, then the property is removed from the vertex.
|
||||||
|
/// Return mgp_error::MGP_ERROR_UNABLE_TO_ALLOCATE if unable to allocate memory for storing the property.
|
||||||
|
/// Return mgp_error::MGP_ERROR_IMMUTABLE_OBJECT if `v` is immutable.
|
||||||
|
/// Return mgp_error::MGP_ERROR_DELETED_OBJECT if `v` has been deleted.
|
||||||
|
/// Return mgp_error::MGP_ERROR_SERIALIZATION_ERROR if `v` has been modified by another transaction.
|
||||||
|
/// Return mgp_error::MGP_ERROR_VALUE_CONVERSION if `property_value` is vertex, edge or path.
|
||||||
|
enum mgp_error mgp_vertex_set_properties(struct mgp_vertex *v, struct mgp_map *properties);
|
||||||
|
|
||||||
/// Add the label to the vertex.
|
/// Add the label to the vertex.
|
||||||
/// If the vertex already has the label, this function does nothing.
|
/// If the vertex already has the label, this function does nothing.
|
||||||
/// Return mgp_error::MGP_ERROR_UNABLE_TO_ALLOCATE if unable to allocate memory for storing the label.
|
/// Return mgp_error::MGP_ERROR_UNABLE_TO_ALLOCATE if unable to allocate memory for storing the label.
|
||||||
@@ -802,6 +829,15 @@ enum mgp_error mgp_edge_get_property(struct mgp_edge *e, const char *property_na
|
|||||||
/// Return mgp_error::MGP_ERROR_VALUE_CONVERSION if `property_value` is vertex, edge or path.
|
/// Return mgp_error::MGP_ERROR_VALUE_CONVERSION if `property_value` is vertex, edge or path.
|
||||||
enum mgp_error mgp_edge_set_property(struct mgp_edge *e, const char *property_name, struct mgp_value *property_value);
|
enum mgp_error mgp_edge_set_property(struct mgp_edge *e, const char *property_name, struct mgp_value *property_value);
|
||||||
|
|
||||||
|
/// Set the value of properties on a vertex.
|
||||||
|
/// When the value is `null`, then the property is removed from the vertex.
|
||||||
|
/// Return mgp_error::MGP_ERROR_UNABLE_TO_ALLOCATE if unable to allocate memory for storing the property.
|
||||||
|
/// Return mgp_error::MGP_ERROR_IMMUTABLE_OBJECT if `v` is immutable.
|
||||||
|
/// Return mgp_error::MGP_ERROR_DELETED_OBJECT if `v` has been deleted.
|
||||||
|
/// Return mgp_error::MGP_ERROR_SERIALIZATION_ERROR if `v` has been modified by another transaction.
|
||||||
|
/// Return mgp_error::MGP_ERROR_VALUE_CONVERSION if `property_value` is vertex, edge or path.
|
||||||
|
enum mgp_error mgp_edge_set_properties(struct mgp_edge *e, struct mgp_map *properties);
|
||||||
|
|
||||||
/// Start iterating over properties stored in the given edge.
|
/// Start iterating over properties stored in the given edge.
|
||||||
/// The properties of the edge are copied when the iterator is created, therefore later changes won't affect them.
|
/// The properties of the edge are copied when the iterator is created, therefore later changes won't affect them.
|
||||||
/// Resulting mgp_properties_iterator needs to be deallocated with
|
/// Resulting mgp_properties_iterator needs to be deallocated with
|
||||||
@@ -852,6 +888,22 @@ enum mgp_error mgp_graph_detach_delete_vertex(struct mgp_graph *graph, struct mg
|
|||||||
enum mgp_error mgp_graph_create_edge(struct mgp_graph *graph, struct mgp_vertex *from, struct mgp_vertex *to,
|
enum mgp_error mgp_graph_create_edge(struct mgp_graph *graph, struct mgp_vertex *from, struct mgp_vertex *to,
|
||||||
struct mgp_edge_type type, struct mgp_memory *memory, struct mgp_edge **result);
|
struct mgp_edge_type type, struct mgp_memory *memory, struct mgp_edge **result);
|
||||||
|
|
||||||
|
/// Change edge from vertex
|
||||||
|
/// Return mgp_error::MGP_ERROR_IMMUTABLE_OBJECT if `graph` is immutable.
|
||||||
|
/// Return mgp_error::MGP_ERROR_UNABLE_TO_ALLOCATE if unable to allocate a mgp_edge.
|
||||||
|
/// Return mgp_error::MGP_ERROR_DELETED_OBJECT if `from` or `to` has been deleted.
|
||||||
|
/// Return mgp_error::MGP_ERROR_SERIALIZATION_ERROR if `from` or `to` has been modified by another transaction.
|
||||||
|
enum mgp_error mgp_graph_edge_set_from(struct mgp_graph *graph, struct mgp_edge *e, struct mgp_vertex *new_from,
|
||||||
|
struct mgp_memory *memory, struct mgp_edge **result);
|
||||||
|
|
||||||
|
/// Change edge to vertex
|
||||||
|
/// Return mgp_error::MGP_ERROR_IMMUTABLE_OBJECT if `graph` is immutable.
|
||||||
|
/// Return mgp_error::MGP_ERROR_UNABLE_TO_ALLOCATE if unable to allocate a mgp_edge.
|
||||||
|
/// Return mgp_error::MGP_ERROR_DELETED_OBJECT if `from` or `to` has been deleted.
|
||||||
|
/// Return mgp_error::MGP_ERROR_SERIALIZATION_ERROR if `from` or `to` has been modified by another transaction.
|
||||||
|
enum mgp_error mgp_graph_edge_set_to(struct mgp_graph *graph, struct mgp_edge *e, struct mgp_vertex *new_to,
|
||||||
|
struct mgp_memory *memory, struct mgp_edge **result);
|
||||||
|
|
||||||
/// Delete an edge from the graph.
|
/// Delete an edge from the graph.
|
||||||
/// Return mgp_error::MGP_ERROR_IMMUTABLE_OBJECT if `graph` is immutable.
|
/// Return mgp_error::MGP_ERROR_IMMUTABLE_OBJECT if `graph` is immutable.
|
||||||
/// Return mgp_error::MGP_ERROR_SERIALIZATION_ERROR if `edge`, its source or destination vertex has been modified by
|
/// Return mgp_error::MGP_ERROR_SERIALIZATION_ERROR if `edge`, its source or destination vertex has been modified by
|
||||||
@@ -1318,6 +1370,13 @@ MGP_ENUM_CLASS mgp_log_level{
|
|||||||
/// to allocate global resources.
|
/// to allocate global resources.
|
||||||
typedef void (*mgp_proc_cb)(struct mgp_list *, struct mgp_graph *, struct mgp_result *, struct mgp_memory *);
|
typedef void (*mgp_proc_cb)(struct mgp_list *, struct mgp_graph *, struct mgp_result *, struct mgp_memory *);
|
||||||
|
|
||||||
|
/// Cleanup for a query module read procedure. Can't be invoked through OpenCypher. Cleans batched stream.
|
||||||
|
typedef void (*mgp_proc_cleanup)();
|
||||||
|
|
||||||
|
/// Initializer for a query module batched read procedure. Can't be invoked through OpenCypher. Initializes batched
|
||||||
|
/// stream.
|
||||||
|
typedef void (*mgp_proc_initializer)(struct mgp_list *, struct mgp_graph *, struct mgp_memory *);
|
||||||
|
|
||||||
/// Register a read-only procedure to a module.
|
/// Register a read-only procedure to a module.
|
||||||
///
|
///
|
||||||
/// The `name` must be a sequence of digits, underscores, lowercase and
|
/// The `name` must be a sequence of digits, underscores, lowercase and
|
||||||
@@ -1342,6 +1401,30 @@ enum mgp_error mgp_module_add_read_procedure(struct mgp_module *module, const ch
|
|||||||
enum mgp_error mgp_module_add_write_procedure(struct mgp_module *module, const char *name, mgp_proc_cb cb,
|
enum mgp_error mgp_module_add_write_procedure(struct mgp_module *module, const char *name, mgp_proc_cb cb,
|
||||||
struct mgp_proc **result);
|
struct mgp_proc **result);
|
||||||
|
|
||||||
|
/// Register a readable batched procedure to a module.
|
||||||
|
///
|
||||||
|
/// The `name` must be a valid identifier, following the same rules as the
|
||||||
|
/// procedure`name` in mgp_module_add_read_procedure.
|
||||||
|
///
|
||||||
|
/// Return mgp_error::MGP_ERROR_UNABLE_TO_ALLOCATE if unable to allocate memory for mgp_proc.
|
||||||
|
/// Return mgp_error::MGP_ERROR_INVALID_ARGUMENT if `name` is not a valid procedure name.
|
||||||
|
/// RETURN mgp_error::MGP_ERROR_LOGIC_ERROR if a procedure with the same name was already registered.
|
||||||
|
enum mgp_error mgp_module_add_batch_read_procedure(struct mgp_module *module, const char *name, mgp_proc_cb cb,
|
||||||
|
mgp_proc_initializer initializer, mgp_proc_cleanup cleanup,
|
||||||
|
struct mgp_proc **result);
|
||||||
|
|
||||||
|
/// Register a writeable batched procedure to a module.
|
||||||
|
///
|
||||||
|
/// The `name` must be a valid identifier, following the same rules as the
|
||||||
|
/// procedure`name` in mgp_module_add_read_procedure.
|
||||||
|
///
|
||||||
|
/// Return mgp_error::MGP_ERROR_UNABLE_TO_ALLOCATE if unable to allocate memory for mgp_proc.
|
||||||
|
/// Return mgp_error::MGP_ERROR_INVALID_ARGUMENT if `name` is not a valid procedure name.
|
||||||
|
/// RETURN mgp_error::MGP_ERROR_LOGIC_ERROR if a procedure with the same name was already registered.
|
||||||
|
enum mgp_error mgp_module_add_batch_write_procedure(struct mgp_module *module, const char *name, mgp_proc_cb cb,
|
||||||
|
mgp_proc_initializer initializer, mgp_proc_cleanup cleanup,
|
||||||
|
struct mgp_proc **result);
|
||||||
|
|
||||||
/// Add a required argument to a procedure.
|
/// Add a required argument to a procedure.
|
||||||
///
|
///
|
||||||
/// The order of adding arguments will correspond to the order the procedure
|
/// The order of adding arguments will correspond to the order the procedure
|
||||||
@@ -1417,7 +1500,10 @@ enum mgp_error mgp_log(enum mgp_log_level log_level, const char *output);
|
|||||||
/// @{
|
/// @{
|
||||||
|
|
||||||
/// Return non-zero if the currently executing procedure should abort as soon as
|
/// Return non-zero if the currently executing procedure should abort as soon as
|
||||||
/// possible.
|
/// possible. If non-zero the reasons are:
|
||||||
|
/// (1) The transaction was requested to be terminated
|
||||||
|
/// (2) The server is gracefully shutting down
|
||||||
|
/// (3) The transaction has hit its timeout threshold
|
||||||
///
|
///
|
||||||
/// Procedures which perform heavyweight processing run the risk of running too
|
/// Procedures which perform heavyweight processing run the risk of running too
|
||||||
/// long and going over the query execution time limit. To prevent this, such
|
/// long and going over the query execution time limit. To prevent this, such
|
||||||
|
|||||||
1267
include/mgp.hpp
1267
include/mgp.hpp
File diff suppressed because it is too large
Load Diff
165
include/mgp.py
165
include/mgp.py
@@ -479,6 +479,12 @@ class Properties:
|
|||||||
except KeyError:
|
except KeyError:
|
||||||
return False
|
return False
|
||||||
|
|
||||||
|
def set_properties(self, properties: dict) -> None:
|
||||||
|
if not self._vertex_or_edge.is_valid():
|
||||||
|
raise InvalidContextError()
|
||||||
|
|
||||||
|
self._vertex_or_edge.set_properties(properties)
|
||||||
|
|
||||||
|
|
||||||
class EdgeType:
|
class EdgeType:
|
||||||
"""Type of an Edge."""
|
"""Type of an Edge."""
|
||||||
@@ -1402,6 +1408,13 @@ class UnsupportedTypingError(Exception):
|
|||||||
super().__init__("Unsupported typing annotation '{}'".format(type_))
|
super().__init__("Unsupported typing annotation '{}'".format(type_))
|
||||||
|
|
||||||
|
|
||||||
|
class UnequalTypesError(Exception):
|
||||||
|
"""Signals a typing annotation is not equal between types"""
|
||||||
|
|
||||||
|
def __init__(self, type1_: typing.Any, type2_: typing.Any):
|
||||||
|
super().__init__(f"Unequal typing annotation '{type1_}' and '{type2_}'")
|
||||||
|
|
||||||
|
|
||||||
def _typing_to_cypher_type(type_):
|
def _typing_to_cypher_type(type_):
|
||||||
"""Convert typing annotation to a _mgp.CypherType instance."""
|
"""Convert typing annotation to a _mgp.CypherType instance."""
|
||||||
simple_types = {
|
simple_types = {
|
||||||
@@ -1514,6 +1527,72 @@ def _typing_to_cypher_type(type_):
|
|||||||
return parse_typing(str(type_))
|
return parse_typing(str(type_))
|
||||||
|
|
||||||
|
|
||||||
|
def _is_typing_same(type1_, type2_):
|
||||||
|
"""Convert typing annotation to a _mgp.CypherType instance."""
|
||||||
|
simple_types = {
|
||||||
|
typing.Any: 1,
|
||||||
|
object: 2,
|
||||||
|
list: 3,
|
||||||
|
Any: 4,
|
||||||
|
bool: 5,
|
||||||
|
str: 6,
|
||||||
|
int: 7,
|
||||||
|
float: 8,
|
||||||
|
Number: 9,
|
||||||
|
Map: 10,
|
||||||
|
Vertex: 11,
|
||||||
|
Edge: 12,
|
||||||
|
Path: 13,
|
||||||
|
Date: 14,
|
||||||
|
LocalTime: 15,
|
||||||
|
LocalDateTime: 16,
|
||||||
|
Duration: 17,
|
||||||
|
}
|
||||||
|
try:
|
||||||
|
return simple_types[type1_] == simple_types[type2_]
|
||||||
|
except KeyError:
|
||||||
|
pass
|
||||||
|
|
||||||
|
if sys.version_info < (3, 8):
|
||||||
|
# skip type checks
|
||||||
|
return True
|
||||||
|
|
||||||
|
complex_type1 = typing.get_origin(type1_)
|
||||||
|
type_args1 = typing.get_args(type2_)
|
||||||
|
|
||||||
|
complex_type2 = typing.get_origin(type1_)
|
||||||
|
type_args2 = typing.get_args(type2_)
|
||||||
|
|
||||||
|
if complex_type2 != complex_type1:
|
||||||
|
raise UnequalTypesError(type1_, type2_)
|
||||||
|
|
||||||
|
if complex_type1 == typing.Union:
|
||||||
|
contains_none_arg1 = type(None) in type_args1
|
||||||
|
contains_none_arg2 = type(None) in type_args2
|
||||||
|
|
||||||
|
if contains_none_arg1 != contains_none_arg2:
|
||||||
|
raise UnequalTypesError(type1_, type2_)
|
||||||
|
|
||||||
|
if contains_none_arg1:
|
||||||
|
types1 = tuple(t for t in type_args1 if t is not type(None)) # noqa E721
|
||||||
|
types2 = tuple(t for t in type_args2 if t is not type(None)) # noqa E721
|
||||||
|
if len(types1) != len(types2):
|
||||||
|
raise UnequalTypesError(types1, types2)
|
||||||
|
if len(types1) == 1:
|
||||||
|
(type_arg1,) = types1
|
||||||
|
(type_arg2,) = types2
|
||||||
|
else:
|
||||||
|
type_arg1 = typing.Union.__getitem__(types1)
|
||||||
|
type_arg2 = typing.Union.__getitem__(types2)
|
||||||
|
return _is_typing_same(type_arg1, type_arg2)
|
||||||
|
elif complex_type1 == list:
|
||||||
|
(type_arg1,) = type_args1
|
||||||
|
(type_arg2,) = type_args2
|
||||||
|
return _is_typing_same(type_arg1, type_arg2)
|
||||||
|
# skip type checks
|
||||||
|
return True
|
||||||
|
|
||||||
|
|
||||||
# Procedure registration
|
# Procedure registration
|
||||||
|
|
||||||
|
|
||||||
@@ -1673,6 +1752,92 @@ def write_proc(func: typing.Callable[..., Record]):
|
|||||||
return _register_proc(func, True)
|
return _register_proc(func, True)
|
||||||
|
|
||||||
|
|
||||||
|
def _register_batch_proc(
|
||||||
|
func: typing.Callable[..., Record], initializer: typing.Callable, cleanup: typing.Callable, is_write: bool
|
||||||
|
):
|
||||||
|
raise_if_does_not_meet_requirements(func)
|
||||||
|
register_func = _mgp.Module.add_batch_write_procedure if is_write else _mgp.Module.add_batch_read_procedure
|
||||||
|
func_sig = inspect.signature(func)
|
||||||
|
func_params = tuple(func_sig.parameters.values())
|
||||||
|
|
||||||
|
initializer_sig = inspect.signature(initializer)
|
||||||
|
initializer_params = tuple(initializer_sig.parameters.values())
|
||||||
|
|
||||||
|
assert (
|
||||||
|
func_params and initializer_params or not func_params and not initializer_params
|
||||||
|
), "Both function params and initializer params must exist or not exist"
|
||||||
|
|
||||||
|
assert len(func_params) == len(initializer_params), "Number of params must be same"
|
||||||
|
|
||||||
|
assert initializer_sig.return_annotation is initializer_sig.empty, "Initializer can't return anything"
|
||||||
|
|
||||||
|
if func_params and func_params[0].annotation is ProcCtx:
|
||||||
|
assert (
|
||||||
|
initializer_params and initializer_params[0].annotation is ProcCtx
|
||||||
|
), "Initializer must have mgp.ProcCtx as first parameter"
|
||||||
|
|
||||||
|
@wraps(func)
|
||||||
|
def wrapper_func(graph, args):
|
||||||
|
return func(ProcCtx(graph), *args)
|
||||||
|
|
||||||
|
@wraps(initializer)
|
||||||
|
def wrapper_initializer(graph, args):
|
||||||
|
return initializer(ProcCtx(graph), *args)
|
||||||
|
|
||||||
|
func_params = func_params[1:]
|
||||||
|
initializer_params = initializer_params[1:]
|
||||||
|
mgp_proc = register_func(_mgp._MODULE, wrapper_func, wrapper_initializer, cleanup)
|
||||||
|
else:
|
||||||
|
|
||||||
|
@wraps(func)
|
||||||
|
def wrapper_func(graph, args):
|
||||||
|
return func(*args)
|
||||||
|
|
||||||
|
@wraps(initializer)
|
||||||
|
def wrapper_initializer(graph, args):
|
||||||
|
return initializer(*args)
|
||||||
|
|
||||||
|
mgp_proc = register_func(_mgp._MODULE, wrapper_func, wrapper_initializer, cleanup)
|
||||||
|
|
||||||
|
for func_param, initializer_param in zip(func_params, initializer_params):
|
||||||
|
func_param_name = func_param.name
|
||||||
|
func_param_type_ = func_param.annotation
|
||||||
|
if func_param_type_ is func_param.empty:
|
||||||
|
func_param_type_ = object
|
||||||
|
initializer_param_type_ = initializer_param.annotation
|
||||||
|
if initializer_param.annotation is initializer_param.empty:
|
||||||
|
initializer_param_type_ = object
|
||||||
|
|
||||||
|
assert _is_typing_same(
|
||||||
|
func_param_type_, initializer_param_type_
|
||||||
|
), "Types of initializer and function must be same"
|
||||||
|
|
||||||
|
func_cypher_type = _typing_to_cypher_type(func_param_type_)
|
||||||
|
if func_param.default is func_param.empty:
|
||||||
|
mgp_proc.add_arg(func_param_name, func_cypher_type)
|
||||||
|
else:
|
||||||
|
mgp_proc.add_opt_arg(func_param_name, func_cypher_type, func_param.default)
|
||||||
|
if func_sig.return_annotation is not func_sig.empty:
|
||||||
|
record = func_sig.return_annotation
|
||||||
|
if not isinstance(record, Record):
|
||||||
|
raise TypeError("Expected '{}' to return 'mgp.Record', got '{}'".format(func.__name__, type(record)))
|
||||||
|
for name, type_ in record.fields.items():
|
||||||
|
if isinstance(type_, Deprecated):
|
||||||
|
cypher_type = _typing_to_cypher_type(type_.field_type)
|
||||||
|
mgp_proc.add_deprecated_result(name, cypher_type)
|
||||||
|
else:
|
||||||
|
mgp_proc.add_result(name, _typing_to_cypher_type(type_))
|
||||||
|
return func
|
||||||
|
|
||||||
|
|
||||||
|
def add_batch_write_proc(func: typing.Callable[..., Record], initializer: typing.Callable, cleanup: typing.Callable):
|
||||||
|
return _register_batch_proc(func, initializer, cleanup, True)
|
||||||
|
|
||||||
|
|
||||||
|
def add_batch_read_proc(func: typing.Callable[..., Record], initializer: typing.Callable, cleanup: typing.Callable):
|
||||||
|
return _register_batch_proc(func, initializer, cleanup, False)
|
||||||
|
|
||||||
|
|
||||||
class InvalidMessageError(Exception):
|
class InvalidMessageError(Exception):
|
||||||
"""
|
"""
|
||||||
Signals using a message instance outside of the registered transformation.
|
Signals using a message instance outside of the registered transformation.
|
||||||
|
|||||||
92
init
92
init
@@ -14,7 +14,6 @@ function print_help () {
|
|||||||
echo "Optional arguments:"
|
echo "Optional arguments:"
|
||||||
echo -e " -h\tdisplay this help and exit"
|
echo -e " -h\tdisplay this help and exit"
|
||||||
echo -e " --without-libs-setup\tskip the step for setting up libs"
|
echo -e " --without-libs-setup\tskip the step for setting up libs"
|
||||||
echo -e " --wsl-quicklisp-proxy \"host:port\"\tquicklist HTTP proxy (this flag + HTTP proxy are required on WSL)"
|
|
||||||
}
|
}
|
||||||
|
|
||||||
function setup_virtualenv () {
|
function setup_virtualenv () {
|
||||||
@@ -35,7 +34,6 @@ function setup_virtualenv () {
|
|||||||
popd > /dev/null
|
popd > /dev/null
|
||||||
}
|
}
|
||||||
|
|
||||||
wsl_quicklisp_proxy=""
|
|
||||||
setup_libs=true
|
setup_libs=true
|
||||||
if [[ $# -eq 1 && "$1" == "-h" ]]; then
|
if [[ $# -eq 1 && "$1" == "-h" ]]; then
|
||||||
print_help
|
print_help
|
||||||
@@ -43,16 +41,6 @@ if [[ $# -eq 1 && "$1" == "-h" ]]; then
|
|||||||
else
|
else
|
||||||
while(($#)); do
|
while(($#)); do
|
||||||
case "$1" in
|
case "$1" in
|
||||||
--wsl-quicklisp-proxy)
|
|
||||||
shift
|
|
||||||
if [[ $# -eq 0 ]]; then
|
|
||||||
echo "Missing proxy URL"
|
|
||||||
print_help
|
|
||||||
exit 1
|
|
||||||
fi
|
|
||||||
wsl_quicklisp_proxy=":proxy \"http://$1/\""
|
|
||||||
shift
|
|
||||||
;;
|
|
||||||
--without-libs-setup)
|
--without-libs-setup)
|
||||||
shift
|
shift
|
||||||
setup_libs=false
|
setup_libs=false
|
||||||
@@ -79,42 +67,19 @@ echo "All packages are in-place..."
|
|||||||
# create a default build directory
|
# create a default build directory
|
||||||
mkdir -p ./build
|
mkdir -p ./build
|
||||||
|
|
||||||
# quicklisp package manager for Common Lisp
|
|
||||||
quicklisp_install_dir="$HOME/quicklisp"
|
|
||||||
if [[ -v QUICKLISP_HOME ]]; then
|
|
||||||
quicklisp_install_dir="${QUICKLISP_HOME}"
|
|
||||||
fi
|
|
||||||
|
|
||||||
if [[ ! -f "${quicklisp_install_dir}/setup.lisp" ]]; then
|
|
||||||
wget -nv https://beta.quicklisp.org/quicklisp.lisp -O quicklisp.lisp || exit 1
|
|
||||||
echo \
|
|
||||||
"
|
|
||||||
(load \"${DIR}/quicklisp.lisp\")
|
|
||||||
(quicklisp-quickstart:install $wsl_quicklisp_proxy :path \"${quicklisp_install_dir}\")
|
|
||||||
" | sbcl --script || exit 1
|
|
||||||
rm -rf quicklisp.lisp || exit 1
|
|
||||||
fi
|
|
||||||
ln -Tfs "$DIR/src/lisp" "${quicklisp_install_dir}/local-projects/lcp"
|
|
||||||
# Install LCP dependencies
|
|
||||||
# TODO: We should at some point cache or have a mirror of packages we use.
|
|
||||||
# TODO: move the installation of LCP's dependencies into ./setup.sh
|
|
||||||
echo \
|
|
||||||
"
|
|
||||||
(load \"${quicklisp_install_dir}/setup.lisp\")
|
|
||||||
(ql:quickload '(:lcp :lcp/test) :silent t)
|
|
||||||
" | sbcl --script
|
|
||||||
|
|
||||||
if [[ "$setup_libs" == "true" ]]; then
|
if [[ "$setup_libs" == "true" ]]; then
|
||||||
# Setup libs (download).
|
# Setup libs (download).
|
||||||
cd libs
|
cd libs
|
||||||
./cleanup.sh
|
./cleanup.sh
|
||||||
./setup.sh
|
./setup.sh
|
||||||
cd ..
|
cd ..
|
||||||
fi
|
fi
|
||||||
|
|
||||||
# Fix for centos 7 during release
|
# Fix for centos 7 during release
|
||||||
if [ "${DISTRO}" = "centos-7" ] || [ "${DISTRO}" = "debian-11" ]; then
|
if [ "${DISTRO}" = "centos-7" ] || [ "${DISTRO}" = "debian-11" ] || [ "${DISTRO}" = "amzn-2" ]; then
|
||||||
python3 -m pip uninstall -y virtualenv
|
if python3 -m pip show virtualenv >/dev/null 2>/dev/null; then
|
||||||
|
python3 -m pip uninstall -y virtualenv
|
||||||
|
fi
|
||||||
python3 -m pip install virtualenv
|
python3 -m pip install virtualenv
|
||||||
fi
|
fi
|
||||||
|
|
||||||
@@ -128,6 +93,10 @@ setup_virtualenv tests/stress
|
|||||||
setup_virtualenv tests/integration/ldap
|
setup_virtualenv tests/integration/ldap
|
||||||
|
|
||||||
# Setup tests dependencies.
|
# Setup tests dependencies.
|
||||||
|
# NOTE: This is commented out because of the build order (at the time of
|
||||||
|
# execution mgclient is not built yet) which makes this setup to fail. mgclient
|
||||||
|
# is built during the make phase. The tests/setup.sh is called under GHA CI
|
||||||
|
# jobs.
|
||||||
# cd tests
|
# cd tests
|
||||||
# ./setup.sh
|
# ./setup.sh
|
||||||
# cd ..
|
# cd ..
|
||||||
@@ -137,21 +106,28 @@ setup_virtualenv tests/integration/ldap
|
|||||||
|
|
||||||
echo "Done installing dependencies for Memgraph"
|
echo "Done installing dependencies for Memgraph"
|
||||||
|
|
||||||
echo "Linking git hooks"
|
echo "Linking git hooks OR skip if .git folder is not there"
|
||||||
for hook in $(find $DIR/.githooks -type f -printf "%f\n"); do
|
if [ -d "$DIR/.git" ]; then
|
||||||
ln -s -f "$DIR/.githooks/$hook" "$DIR/.git/hooks/$hook"
|
for hook in $(find $DIR/.githooks -type f -printf "%f\n"); do
|
||||||
echo "Added $hook hook"
|
ln -s -f "$DIR/.githooks/$hook" "$DIR/.git/hooks/$hook"
|
||||||
done;
|
echo "Added $hook hook"
|
||||||
|
done;
|
||||||
|
else
|
||||||
|
echo "WARNING: .git folder not present, skip adding hooks"
|
||||||
|
fi
|
||||||
|
|
||||||
# Install precommit hook
|
# Install precommit hook except on old operating systems because we don't
|
||||||
python3 -m pip install pre-commit
|
# develop on them -> pre-commit hook not required -> we can use latest
|
||||||
python3 -m pre_commit install
|
# packages.
|
||||||
|
if [ "${DISTRO}" != "centos-7" ] && [ "$DISTRO" != "debian-10" ] && [ "${DISTRO}" != "ubuntu-18.04" ] && [ "${DISTRO}" != "amzn-2" ]; then
|
||||||
# Install py format tools
|
python3 -m pip install pre-commit
|
||||||
echo "Install black formatter"
|
python3 -m pre_commit install
|
||||||
python3 -m pip install black==22.8.*
|
# Install py format tools for usage during the development.
|
||||||
echo "Install isort"
|
echo "Install black formatter"
|
||||||
python3 -m pip install isort==5.10.*
|
python3 -m pip install black==23.1.*
|
||||||
|
echo "Install isort"
|
||||||
|
python3 -m pip install isort==5.12.*
|
||||||
|
fi
|
||||||
|
|
||||||
# Link `include/mgp.py` with `release/mgp/mgp.py`
|
# Link `include/mgp.py` with `release/mgp/mgp.py`
|
||||||
ln -v -f include/mgp.py release/mgp/mgp.py
|
ln -v -f include/mgp.py release/mgp/mgp.py
|
||||||
|
|||||||
1
libs/.gitignore
vendored
1
libs/.gitignore
vendored
@@ -6,3 +6,4 @@
|
|||||||
!__main.cpp
|
!__main.cpp
|
||||||
!pulsar.patch
|
!pulsar.patch
|
||||||
!antlr4.10.1.patch
|
!antlr4.10.1.patch
|
||||||
|
!rocksdb8.1.1.patch
|
||||||
|
|||||||
@@ -12,6 +12,7 @@ find_package(Boost 1.78 REQUIRED)
|
|||||||
find_package(BZip2 1.0.6 REQUIRED)
|
find_package(BZip2 1.0.6 REQUIRED)
|
||||||
find_package(Threads REQUIRED)
|
find_package(Threads REQUIRED)
|
||||||
set(GFLAGS_NOTHREADS OFF)
|
set(GFLAGS_NOTHREADS OFF)
|
||||||
|
# NOTE: config/generate.py depends on the gflags help XML format.
|
||||||
find_package(gflags REQUIRED)
|
find_package(gflags REQUIRED)
|
||||||
find_package(fmt 8.0.1)
|
find_package(fmt 8.0.1)
|
||||||
find_package(Jemalloc REQUIRED)
|
find_package(Jemalloc REQUIRED)
|
||||||
@@ -28,6 +29,7 @@ function(import_header_library name include_dir)
|
|||||||
set(${_upper_name}_INCLUDE_DIR ${include_dir} CACHE FILEPATH
|
set(${_upper_name}_INCLUDE_DIR ${include_dir} CACHE FILEPATH
|
||||||
"Path to ${name} include directory" FORCE)
|
"Path to ${name} include directory" FORCE)
|
||||||
mark_as_advanced(${_upper_name}_INCLUDE_DIR)
|
mark_as_advanced(${_upper_name}_INCLUDE_DIR)
|
||||||
|
add_library(lib::${name} ALIAS ${name})
|
||||||
endfunction(import_header_library)
|
endfunction(import_header_library)
|
||||||
|
|
||||||
function(import_library name type location include_dir)
|
function(import_library name type location include_dir)
|
||||||
@@ -256,3 +258,10 @@ import_external_library(librdtsc STATIC
|
|||||||
${CMAKE_CURRENT_SOURCE_DIR}/librdtsc/include
|
${CMAKE_CURRENT_SOURCE_DIR}/librdtsc/include
|
||||||
CMAKE_ARGS ${MG_LIBRDTSC_CMAKE_ARGS}
|
CMAKE_ARGS ${MG_LIBRDTSC_CMAKE_ARGS}
|
||||||
BUILD_COMMAND $(MAKE) rdtsc)
|
BUILD_COMMAND $(MAKE) rdtsc)
|
||||||
|
|
||||||
|
# setup ctre
|
||||||
|
import_header_library(ctre ${CMAKE_CURRENT_SOURCE_DIR})
|
||||||
|
|
||||||
|
# setup absl (cmake sub_directory tolerant)
|
||||||
|
set(ABSL_PROPAGATE_CXX_STD ON)
|
||||||
|
add_subdirectory(absl EXCLUDE_FROM_ALL)
|
||||||
|
|||||||
13
libs/rocksdb8.1.1.patch
Normal file
13
libs/rocksdb8.1.1.patch
Normal file
@@ -0,0 +1,13 @@
|
|||||||
|
diff --git a/CMakeLists.txt b/CMakeLists.txt
|
||||||
|
index 598c728..816c705 100644
|
||||||
|
--- a/CMakeLists.txt
|
||||||
|
+++ b/CMakeLists.txt
|
||||||
|
@@ -1242,7 +1242,7 @@ if(NOT WIN32 OR ROCKSDB_INSTALL_ON_WINDOWS)
|
||||||
|
|
||||||
|
if(ROCKSDB_BUILD_SHARED)
|
||||||
|
install(
|
||||||
|
- TARGETS ${ROCKSDB_SHARED_LIB}
|
||||||
|
+ TARGETS ${ROCKSDB_SHARED_LIB} OPTIONAL
|
||||||
|
EXPORT RocksDBTargets
|
||||||
|
COMPONENT runtime
|
||||||
|
ARCHIVE DESTINATION "${CMAKE_INSTALL_LIBDIR}"
|
||||||
@@ -71,8 +71,8 @@ file_get_try_double () {
|
|||||||
if [ -z "$primary_url" ]; then echo "Primary should not be empty." && exit 1; fi
|
if [ -z "$primary_url" ]; then echo "Primary should not be empty." && exit 1; fi
|
||||||
if [ -z "$secondary_url" ]; then echo "Secondary should not be empty." && exit 1; fi
|
if [ -z "$secondary_url" ]; then echo "Secondary should not be empty." && exit 1; fi
|
||||||
filename="$(basename "$secondary_url")"
|
filename="$(basename "$secondary_url")"
|
||||||
wget -nv "$primary_url" -O "$filename" || wget -nv "$secondary_url" -O "$filename" || exit 1
|
# Redirect primary/cache to /dev/null to make it less confusing for a new contributor because only CI has access to the cache.
|
||||||
echo ""
|
wget -nv "$primary_url" -O "$filename" >/dev/null 2>&1 || wget -nv "$secondary_url" -O "$filename" || exit 1
|
||||||
}
|
}
|
||||||
|
|
||||||
repo_clone_try_double () {
|
repo_clone_try_double () {
|
||||||
@@ -86,8 +86,8 @@ repo_clone_try_double () {
|
|||||||
if [ -z "$secondary_url" ]; then echo "Secondary should not be empty." && exit 1; fi
|
if [ -z "$secondary_url" ]; then echo "Secondary should not be empty." && exit 1; fi
|
||||||
if [ -z "$folder_name" ]; then echo "Clone folder should not be empty." && exit 1; fi
|
if [ -z "$folder_name" ]; then echo "Clone folder should not be empty." && exit 1; fi
|
||||||
if [ -z "$ref" ]; then echo "Git clone ref should not be empty." && exit 1; fi
|
if [ -z "$ref" ]; then echo "Git clone ref should not be empty." && exit 1; fi
|
||||||
clone "$primary_url" "$folder_name" "$ref" "$shallow" || clone "$secondary_url" "$folder_name" "$ref" "$shallow" || exit 1
|
# Redirect primary/cache to /dev/null to make it less confusing for a new contributor because only CI has access to the cache.
|
||||||
echo ""
|
clone "$primary_url" "$folder_name" "$ref" "$shallow" >/dev/null 2>&1 || clone "$secondary_url" "$folder_name" "$ref" "$shallow" || exit 1
|
||||||
}
|
}
|
||||||
|
|
||||||
# List all dependencies.
|
# List all dependencies.
|
||||||
@@ -117,11 +117,13 @@ declare -A primary_urls=(
|
|||||||
["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"
|
||||||
["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-5.6.0-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"
|
||||||
["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"
|
||||||
|
["ctre"]="http://$local_cache_host/file/hanickadot/compile-time-regular-expressions/v3.7.2/single-header/ctre.hpp"
|
||||||
|
["absl"]="https://$local_cache_host/git/abseil-cpp.git"
|
||||||
)
|
)
|
||||||
|
|
||||||
# The goal of secondary urls is to have links to the "source of truth" of
|
# The goal of secondary urls is to have links to the "source of truth" of
|
||||||
@@ -139,14 +141,16 @@ declare -A secondary_urls=(
|
|||||||
["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"]="https://github.com/memgraph/mgconsole.git"
|
||||||
["spdlog"]="https://github.com/gabime/spdlog"
|
["spdlog"]="https://github.com/gabime/spdlog"
|
||||||
["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://dist.neo4j.org/neo4j-community-5.6.0-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"
|
||||||
["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"
|
||||||
|
["ctre"]="https://raw.githubusercontent.com/hanickadot/compile-time-regular-expressions/v3.7.2/single-header/ctre.hpp"
|
||||||
|
["absl"]="https://github.com/abseil/abseil-cpp.git"
|
||||||
)
|
)
|
||||||
|
|
||||||
# antlr
|
# antlr
|
||||||
@@ -180,9 +184,9 @@ repo_clone_try_double "${primary_urls[libbcrypt]}" "${secondary_urls[libbcrypt]}
|
|||||||
|
|
||||||
# neo4j
|
# neo4j
|
||||||
file_get_try_double "${primary_urls[neo4j]}" "${secondary_urls[neo4j]}"
|
file_get_try_double "${primary_urls[neo4j]}" "${secondary_urls[neo4j]}"
|
||||||
tar -xzf neo4j-community-3.2.3-unix.tar.gz
|
tar -xzf neo4j-community-5.6.0-unix.tar.gz
|
||||||
mv neo4j-community-3.2.3 neo4j
|
mv neo4j-community-5.6.0 neo4j
|
||||||
rm neo4j-community-3.2.3-unix.tar.gz
|
rm neo4j-community-5.6.0-unix.tar.gz
|
||||||
|
|
||||||
# nlohmann json
|
# nlohmann json
|
||||||
# We wget header instead of cloning repo since repo is huge (lots of test data).
|
# We wget header instead of cloning repo since repo is huge (lots of test data).
|
||||||
@@ -192,10 +196,10 @@ cd json
|
|||||||
file_get_try_double "${primary_urls[nlohmann]}" "${secondary_urls[nlohmann]}"
|
file_get_try_double "${primary_urls[nlohmann]}" "${secondary_urls[nlohmann]}"
|
||||||
cd ..
|
cd ..
|
||||||
|
|
||||||
rocksdb_tag="v6.14.6" # (2020-10-14)
|
rocksdb_tag="v8.1.1" # (2023-04-21)
|
||||||
repo_clone_try_double "${primary_urls[rocksdb]}" "${secondary_urls[rocksdb]}" "rocksdb" "$rocksdb_tag" true
|
repo_clone_try_double "${primary_urls[rocksdb]}" "${secondary_urls[rocksdb]}" "rocksdb" "$rocksdb_tag" true
|
||||||
pushd rocksdb
|
pushd rocksdb
|
||||||
git apply ../rocksdb.patch
|
git apply ../rocksdb8.1.1.patch
|
||||||
popd
|
popd
|
||||||
|
|
||||||
# mgclient
|
# mgclient
|
||||||
@@ -208,7 +212,7 @@ pymgclient_tag="4f85c179e56302d46a1e3e2cf43509db65f062b3" # (2021-01-15)
|
|||||||
repo_clone_try_double "${primary_urls[pymgclient]}" "${secondary_urls[pymgclient]}" "pymgclient" "$pymgclient_tag"
|
repo_clone_try_double "${primary_urls[pymgclient]}" "${secondary_urls[pymgclient]}" "pymgclient" "$pymgclient_tag"
|
||||||
|
|
||||||
# mgconsole
|
# mgconsole
|
||||||
mgconsole_tag="v1.3.0" # (2022-11-20)
|
mgconsole_tag="v1.4.0" # (2023-05-21)
|
||||||
repo_clone_try_double "${primary_urls[mgconsole]}" "${secondary_urls[mgconsole]}" "mgconsole" "$mgconsole_tag" true
|
repo_clone_try_double "${primary_urls[mgconsole]}" "${secondary_urls[mgconsole]}" "mgconsole" "$mgconsole_tag" true
|
||||||
|
|
||||||
spdlog_tag="v1.9.2" # (2021-08-12)
|
spdlog_tag="v1.9.2" # (2021-08-12)
|
||||||
@@ -238,3 +242,13 @@ repo_clone_try_double "${primary_urls[librdtsc]}" "${secondary_urls[librdtsc]}"
|
|||||||
pushd librdtsc
|
pushd librdtsc
|
||||||
git apply ../librdtsc.patch
|
git apply ../librdtsc.patch
|
||||||
popd
|
popd
|
||||||
|
|
||||||
|
#ctre
|
||||||
|
mkdir -p ctre
|
||||||
|
cd ctre
|
||||||
|
file_get_try_double "${primary_urls[ctre]}" "${secondary_urls[ctre]}"
|
||||||
|
cd ..
|
||||||
|
|
||||||
|
# abseil 20230125.3
|
||||||
|
absl_ref="20230125.3"
|
||||||
|
repo_clone_try_double "${primary_urls[absl]}" "${secondary_urls[absl]}" "absl" "$absl_ref"
|
||||||
|
|||||||
@@ -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: 2027-08-03
|
CHANGE DATE: 2027-02-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.
|
||||||
|
|||||||
202
licenses/third-party/abseil-cpp/LICENSE
vendored
Normal file
202
licenses/third-party/abseil-cpp/LICENSE
vendored
Normal file
@@ -0,0 +1,202 @@
|
|||||||
|
|
||||||
|
Apache License
|
||||||
|
Version 2.0, January 2004
|
||||||
|
https://www.apache.org/licenses/
|
||||||
|
|
||||||
|
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
|
||||||
|
|
||||||
|
1. Definitions.
|
||||||
|
|
||||||
|
"License" shall mean the terms and conditions for use, reproduction,
|
||||||
|
and distribution as defined by Sections 1 through 9 of this document.
|
||||||
|
|
||||||
|
"Licensor" shall mean the copyright owner or entity authorized by
|
||||||
|
the copyright owner that is granting the License.
|
||||||
|
|
||||||
|
"Legal Entity" shall mean the union of the acting entity and all
|
||||||
|
other entities that control, are controlled by, or are under common
|
||||||
|
control with that entity. For the purposes of this definition,
|
||||||
|
"control" means (i) the power, direct or indirect, to cause the
|
||||||
|
direction or management of such entity, whether by contract or
|
||||||
|
otherwise, or (ii) ownership of fifty percent (50%) or more of the
|
||||||
|
outstanding shares, or (iii) beneficial ownership of such entity.
|
||||||
|
|
||||||
|
"You" (or "Your") shall mean an individual or Legal Entity
|
||||||
|
exercising permissions granted by this License.
|
||||||
|
|
||||||
|
"Source" form shall mean the preferred form for making modifications,
|
||||||
|
including but not limited to software source code, documentation
|
||||||
|
source, and configuration files.
|
||||||
|
|
||||||
|
"Object" form shall mean any form resulting from mechanical
|
||||||
|
transformation or translation of a Source form, including but
|
||||||
|
not limited to compiled object code, generated documentation,
|
||||||
|
and conversions to other media types.
|
||||||
|
|
||||||
|
"Work" shall mean the work of authorship, whether in Source or
|
||||||
|
Object form, made available under the License, as indicated by a
|
||||||
|
copyright notice that is included in or attached to the work
|
||||||
|
(an example is provided in the Appendix below).
|
||||||
|
|
||||||
|
"Derivative Works" shall mean any work, whether in Source or Object
|
||||||
|
form, that is based on (or derived from) the Work and for which the
|
||||||
|
editorial revisions, annotations, elaborations, or other modifications
|
||||||
|
represent, as a whole, an original work of authorship. For the purposes
|
||||||
|
of this License, Derivative Works shall not include works that remain
|
||||||
|
separable from, or merely link (or bind by name) to the interfaces of,
|
||||||
|
the Work and Derivative Works thereof.
|
||||||
|
|
||||||
|
"Contribution" shall mean any work of authorship, including
|
||||||
|
the original version of the Work and any modifications or additions
|
||||||
|
to that Work or Derivative Works thereof, that is intentionally
|
||||||
|
submitted to Licensor for inclusion in the Work by the copyright owner
|
||||||
|
or by an individual or Legal Entity authorized to submit on behalf of
|
||||||
|
the copyright owner. For the purposes of this definition, "submitted"
|
||||||
|
means any form of electronic, verbal, or written communication sent
|
||||||
|
to the Licensor or its representatives, including but not limited to
|
||||||
|
communication on electronic mailing lists, source code control systems,
|
||||||
|
and issue tracking systems that are managed by, or on behalf of, the
|
||||||
|
Licensor for the purpose of discussing and improving the Work, but
|
||||||
|
excluding communication that is conspicuously marked or otherwise
|
||||||
|
designated in writing by the copyright owner as "Not a Contribution."
|
||||||
|
|
||||||
|
"Contributor" shall mean Licensor and any individual or Legal Entity
|
||||||
|
on behalf of whom a Contribution has been received by Licensor and
|
||||||
|
subsequently incorporated within the Work.
|
||||||
|
|
||||||
|
2. Grant of Copyright License. Subject to the terms and conditions of
|
||||||
|
this License, each Contributor hereby grants to You a perpetual,
|
||||||
|
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
|
||||||
|
copyright license to reproduce, prepare Derivative Works of,
|
||||||
|
publicly display, publicly perform, sublicense, and distribute the
|
||||||
|
Work and such Derivative Works in Source or Object form.
|
||||||
|
|
||||||
|
3. Grant of Patent License. Subject to the terms and conditions of
|
||||||
|
this License, each Contributor hereby grants to You a perpetual,
|
||||||
|
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
|
||||||
|
(except as stated in this section) patent license to make, have made,
|
||||||
|
use, offer to sell, sell, import, and otherwise transfer the Work,
|
||||||
|
where such license applies only to those patent claims licensable
|
||||||
|
by such Contributor that are necessarily infringed by their
|
||||||
|
Contribution(s) alone or by combination of their Contribution(s)
|
||||||
|
with the Work to which such Contribution(s) was submitted. If You
|
||||||
|
institute patent litigation against any entity (including a
|
||||||
|
cross-claim or counterclaim in a lawsuit) alleging that the Work
|
||||||
|
or a Contribution incorporated within the Work constitutes direct
|
||||||
|
or contributory patent infringement, then any patent licenses
|
||||||
|
granted to You under this License for that Work shall terminate
|
||||||
|
as of the date such litigation is filed.
|
||||||
|
|
||||||
|
4. Redistribution. You may reproduce and distribute copies of the
|
||||||
|
Work or Derivative Works thereof in any medium, with or without
|
||||||
|
modifications, and in Source or Object form, provided that You
|
||||||
|
meet the following conditions:
|
||||||
|
|
||||||
|
(a) You must give any other recipients of the Work or
|
||||||
|
Derivative Works a copy of this License; and
|
||||||
|
|
||||||
|
(b) You must cause any modified files to carry prominent notices
|
||||||
|
stating that You changed the files; and
|
||||||
|
|
||||||
|
(c) You must retain, in the Source form of any Derivative Works
|
||||||
|
that You distribute, all copyright, patent, trademark, and
|
||||||
|
attribution notices from the Source form of the Work,
|
||||||
|
excluding those notices that do not pertain to any part of
|
||||||
|
the Derivative Works; and
|
||||||
|
|
||||||
|
(d) If the Work includes a "NOTICE" text file as part of its
|
||||||
|
distribution, then any Derivative Works that You distribute must
|
||||||
|
include a readable copy of the attribution notices contained
|
||||||
|
within such NOTICE file, excluding those notices that do not
|
||||||
|
pertain to any part of the Derivative Works, in at least one
|
||||||
|
of the following places: within a NOTICE text file distributed
|
||||||
|
as part of the Derivative Works; within the Source form or
|
||||||
|
documentation, if provided along with the Derivative Works; or,
|
||||||
|
within a display generated by the Derivative Works, if and
|
||||||
|
wherever such third-party notices normally appear. The contents
|
||||||
|
of the NOTICE file are for informational purposes only and
|
||||||
|
do not modify the License. You may add Your own attribution
|
||||||
|
notices within Derivative Works that You distribute, alongside
|
||||||
|
or as an addendum to the NOTICE text from the Work, provided
|
||||||
|
that such additional attribution notices cannot be construed
|
||||||
|
as modifying the License.
|
||||||
|
|
||||||
|
You may add Your own copyright statement to Your modifications and
|
||||||
|
may provide additional or different license terms and conditions
|
||||||
|
for use, reproduction, or distribution of Your modifications, or
|
||||||
|
for any such Derivative Works as a whole, provided Your use,
|
||||||
|
reproduction, and distribution of the Work otherwise complies with
|
||||||
|
the conditions stated in this License.
|
||||||
|
|
||||||
|
5. Submission of Contributions. Unless You explicitly state otherwise,
|
||||||
|
any Contribution intentionally submitted for inclusion in the Work
|
||||||
|
by You to the Licensor shall be under the terms and conditions of
|
||||||
|
this License, without any additional terms or conditions.
|
||||||
|
Notwithstanding the above, nothing herein shall supersede or modify
|
||||||
|
the terms of any separate license agreement you may have executed
|
||||||
|
with Licensor regarding such Contributions.
|
||||||
|
|
||||||
|
6. Trademarks. This License does not grant permission to use the trade
|
||||||
|
names, trademarks, service marks, or product names of the Licensor,
|
||||||
|
except as required for reasonable and customary use in describing the
|
||||||
|
origin of the Work and reproducing the content of the NOTICE file.
|
||||||
|
|
||||||
|
7. Disclaimer of Warranty. Unless required by applicable law or
|
||||||
|
agreed to in writing, Licensor provides the Work (and each
|
||||||
|
Contributor provides its Contributions) on an "AS IS" BASIS,
|
||||||
|
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
|
||||||
|
implied, including, without limitation, any warranties or conditions
|
||||||
|
of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
|
||||||
|
PARTICULAR PURPOSE. You are solely responsible for determining the
|
||||||
|
appropriateness of using or redistributing the Work and assume any
|
||||||
|
risks associated with Your exercise of permissions under this License.
|
||||||
|
|
||||||
|
8. Limitation of Liability. In no event and under no legal theory,
|
||||||
|
whether in tort (including negligence), contract, or otherwise,
|
||||||
|
unless required by applicable law (such as deliberate and grossly
|
||||||
|
negligent acts) or agreed to in writing, shall any Contributor be
|
||||||
|
liable to You for damages, including any direct, indirect, special,
|
||||||
|
incidental, or consequential damages of any character arising as a
|
||||||
|
result of this License or out of the use or inability to use the
|
||||||
|
Work (including but not limited to damages for loss of goodwill,
|
||||||
|
work stoppage, computer failure or malfunction, or any and all
|
||||||
|
other commercial damages or losses), even if such Contributor
|
||||||
|
has been advised of the possibility of such damages.
|
||||||
|
|
||||||
|
9. Accepting Warranty or Additional Liability. While redistributing
|
||||||
|
the Work or Derivative Works thereof, You may choose to offer,
|
||||||
|
and charge a fee for, acceptance of support, warranty, indemnity,
|
||||||
|
or other liability obligations and/or rights consistent with this
|
||||||
|
License. However, in accepting such obligations, You may act only
|
||||||
|
on Your own behalf and on Your sole responsibility, not on behalf
|
||||||
|
of any other Contributor, and only if You agree to indemnify,
|
||||||
|
defend, and hold each Contributor harmless for any liability
|
||||||
|
incurred by, or claims asserted against, such Contributor by reason
|
||||||
|
of your accepting any such warranty or additional liability.
|
||||||
|
|
||||||
|
END OF TERMS AND CONDITIONS
|
||||||
|
|
||||||
|
APPENDIX: How to apply the Apache License to your work.
|
||||||
|
|
||||||
|
To apply the Apache License to your work, attach the following
|
||||||
|
boilerplate notice, with the fields enclosed by brackets "[]"
|
||||||
|
replaced with your own identifying information. (Don't include
|
||||||
|
the brackets!) The text should be enclosed in the appropriate
|
||||||
|
comment syntax for the file format. We also recommend that a
|
||||||
|
file or class name and description of purpose be included on the
|
||||||
|
same "printed page" as the copyright notice for easier
|
||||||
|
identification within third-party archives.
|
||||||
|
|
||||||
|
Copyright [yyyy] [name of copyright owner]
|
||||||
|
|
||||||
|
Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
you may not use this file except in compliance with the License.
|
||||||
|
You may obtain a copy of the License at
|
||||||
|
|
||||||
|
https://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
|
||||||
|
Unless required by applicable law or agreed to in writing, software
|
||||||
|
distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
See the License for the specific language governing permissions and
|
||||||
|
limitations under the License.
|
||||||
218
licenses/third-party/compile-time-regular-expressions/LICENSE
vendored
Normal file
218
licenses/third-party/compile-time-regular-expressions/LICENSE
vendored
Normal file
@@ -0,0 +1,218 @@
|
|||||||
|
Apache License
|
||||||
|
Version 2.0, January 2004
|
||||||
|
http://www.apache.org/licenses/
|
||||||
|
|
||||||
|
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
|
||||||
|
|
||||||
|
1. Definitions.
|
||||||
|
|
||||||
|
"License" shall mean the terms and conditions for use, reproduction,
|
||||||
|
and distribution as defined by Sections 1 through 9 of this document.
|
||||||
|
|
||||||
|
"Licensor" shall mean the copyright owner or entity authorized by
|
||||||
|
the copyright owner that is granting the License.
|
||||||
|
|
||||||
|
"Legal Entity" shall mean the union of the acting entity and all
|
||||||
|
other entities that control, are controlled by, or are under common
|
||||||
|
control with that entity. For the purposes of this definition,
|
||||||
|
"control" means (i) the power, direct or indirect, to cause the
|
||||||
|
direction or management of such entity, whether by contract or
|
||||||
|
otherwise, or (ii) ownership of fifty percent (50%) or more of the
|
||||||
|
outstanding shares, or (iii) beneficial ownership of such entity.
|
||||||
|
|
||||||
|
"You" (or "Your") shall mean an individual or Legal Entity
|
||||||
|
exercising permissions granted by this License.
|
||||||
|
|
||||||
|
"Source" form shall mean the preferred form for making modifications,
|
||||||
|
including but not limited to software source code, documentation
|
||||||
|
source, and configuration files.
|
||||||
|
|
||||||
|
"Object" form shall mean any form resulting from mechanical
|
||||||
|
transformation or translation of a Source form, including but
|
||||||
|
not limited to compiled object code, generated documentation,
|
||||||
|
and conversions to other media types.
|
||||||
|
|
||||||
|
"Work" shall mean the work of authorship, whether in Source or
|
||||||
|
Object form, made available under the License, as indicated by a
|
||||||
|
copyright notice that is included in or attached to the work
|
||||||
|
(an example is provided in the Appendix below).
|
||||||
|
|
||||||
|
"Derivative Works" shall mean any work, whether in Source or Object
|
||||||
|
form, that is based on (or derived from) the Work and for which the
|
||||||
|
editorial revisions, annotations, elaborations, or other modifications
|
||||||
|
represent, as a whole, an original work of authorship. For the purposes
|
||||||
|
of this License, Derivative Works shall not include works that remain
|
||||||
|
separable from, or merely link (or bind by name) to the interfaces of,
|
||||||
|
the Work and Derivative Works thereof.
|
||||||
|
|
||||||
|
"Contribution" shall mean any work of authorship, including
|
||||||
|
the original version of the Work and any modifications or additions
|
||||||
|
to that Work or Derivative Works thereof, that is intentionally
|
||||||
|
submitted to Licensor for inclusion in the Work by the copyright owner
|
||||||
|
or by an individual or Legal Entity authorized to submit on behalf of
|
||||||
|
the copyright owner. For the purposes of this definition, "submitted"
|
||||||
|
means any form of electronic, verbal, or written communication sent
|
||||||
|
to the Licensor or its representatives, including but not limited to
|
||||||
|
communication on electronic mailing lists, source code control systems,
|
||||||
|
and issue tracking systems that are managed by, or on behalf of, the
|
||||||
|
Licensor for the purpose of discussing and improving the Work, but
|
||||||
|
excluding communication that is conspicuously marked or otherwise
|
||||||
|
designated in writing by the copyright owner as "Not a Contribution."
|
||||||
|
|
||||||
|
"Contributor" shall mean Licensor and any individual or Legal Entity
|
||||||
|
on behalf of whom a Contribution has been received by Licensor and
|
||||||
|
subsequently incorporated within the Work.
|
||||||
|
|
||||||
|
2. Grant of Copyright License. Subject to the terms and conditions of
|
||||||
|
this License, each Contributor hereby grants to You a perpetual,
|
||||||
|
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
|
||||||
|
copyright license to reproduce, prepare Derivative Works of,
|
||||||
|
publicly display, publicly perform, sublicense, and distribute the
|
||||||
|
Work and such Derivative Works in Source or Object form.
|
||||||
|
|
||||||
|
3. Grant of Patent License. Subject to the terms and conditions of
|
||||||
|
this License, each Contributor hereby grants to You a perpetual,
|
||||||
|
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
|
||||||
|
(except as stated in this section) patent license to make, have made,
|
||||||
|
use, offer to sell, sell, import, and otherwise transfer the Work,
|
||||||
|
where such license applies only to those patent claims licensable
|
||||||
|
by such Contributor that are necessarily infringed by their
|
||||||
|
Contribution(s) alone or by combination of their Contribution(s)
|
||||||
|
with the Work to which such Contribution(s) was submitted. If You
|
||||||
|
institute patent litigation against any entity (including a
|
||||||
|
cross-claim or counterclaim in a lawsuit) alleging that the Work
|
||||||
|
or a Contribution incorporated within the Work constitutes direct
|
||||||
|
or contributory patent infringement, then any patent licenses
|
||||||
|
granted to You under this License for that Work shall terminate
|
||||||
|
as of the date such litigation is filed.
|
||||||
|
|
||||||
|
4. Redistribution. You may reproduce and distribute copies of the
|
||||||
|
Work or Derivative Works thereof in any medium, with or without
|
||||||
|
modifications, and in Source or Object form, provided that You
|
||||||
|
meet the following conditions:
|
||||||
|
|
||||||
|
(a) You must give any other recipients of the Work or
|
||||||
|
Derivative Works a copy of this License; and
|
||||||
|
|
||||||
|
(b) You must cause any modified files to carry prominent notices
|
||||||
|
stating that You changed the files; and
|
||||||
|
|
||||||
|
(c) You must retain, in the Source form of any Derivative Works
|
||||||
|
that You distribute, all copyright, patent, trademark, and
|
||||||
|
attribution notices from the Source form of the Work,
|
||||||
|
excluding those notices that do not pertain to any part of
|
||||||
|
the Derivative Works; and
|
||||||
|
|
||||||
|
(d) If the Work includes a "NOTICE" text file as part of its
|
||||||
|
distribution, then any Derivative Works that You distribute must
|
||||||
|
include a readable copy of the attribution notices contained
|
||||||
|
within such NOTICE file, excluding those notices that do not
|
||||||
|
pertain to any part of the Derivative Works, in at least one
|
||||||
|
of the following places: within a NOTICE text file distributed
|
||||||
|
as part of the Derivative Works; within the Source form or
|
||||||
|
documentation, if provided along with the Derivative Works; or,
|
||||||
|
within a display generated by the Derivative Works, if and
|
||||||
|
wherever such third-party notices normally appear. The contents
|
||||||
|
of the NOTICE file are for informational purposes only and
|
||||||
|
do not modify the License. You may add Your own attribution
|
||||||
|
notices within Derivative Works that You distribute, alongside
|
||||||
|
or as an addendum to the NOTICE text from the Work, provided
|
||||||
|
that such additional attribution notices cannot be construed
|
||||||
|
as modifying the License.
|
||||||
|
|
||||||
|
You may add Your own copyright statement to Your modifications and
|
||||||
|
may provide additional or different license terms and conditions
|
||||||
|
for use, reproduction, or distribution of Your modifications, or
|
||||||
|
for any such Derivative Works as a whole, provided Your use,
|
||||||
|
reproduction, and distribution of the Work otherwise complies with
|
||||||
|
the conditions stated in this License.
|
||||||
|
|
||||||
|
5. Submission of Contributions. Unless You explicitly state otherwise,
|
||||||
|
any Contribution intentionally submitted for inclusion in the Work
|
||||||
|
by You to the Licensor shall be under the terms and conditions of
|
||||||
|
this License, without any additional terms or conditions.
|
||||||
|
Notwithstanding the above, nothing herein shall supersede or modify
|
||||||
|
the terms of any separate license agreement you may have executed
|
||||||
|
with Licensor regarding such Contributions.
|
||||||
|
|
||||||
|
6. Trademarks. This License does not grant permission to use the trade
|
||||||
|
names, trademarks, service marks, or product names of the Licensor,
|
||||||
|
except as required for reasonable and customary use in describing the
|
||||||
|
origin of the Work and reproducing the content of the NOTICE file.
|
||||||
|
|
||||||
|
7. Disclaimer of Warranty. Unless required by applicable law or
|
||||||
|
agreed to in writing, Licensor provides the Work (and each
|
||||||
|
Contributor provides its Contributions) on an "AS IS" BASIS,
|
||||||
|
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
|
||||||
|
implied, including, without limitation, any warranties or conditions
|
||||||
|
of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
|
||||||
|
PARTICULAR PURPOSE. You are solely responsible for determining the
|
||||||
|
appropriateness of using or redistributing the Work and assume any
|
||||||
|
risks associated with Your exercise of permissions under this License.
|
||||||
|
|
||||||
|
8. Limitation of Liability. In no event and under no legal theory,
|
||||||
|
whether in tort (including negligence), contract, or otherwise,
|
||||||
|
unless required by applicable law (such as deliberate and grossly
|
||||||
|
negligent acts) or agreed to in writing, shall any Contributor be
|
||||||
|
liable to You for damages, including any direct, indirect, special,
|
||||||
|
incidental, or consequential damages of any character arising as a
|
||||||
|
result of this License or out of the use or inability to use the
|
||||||
|
Work (including but not limited to damages for loss of goodwill,
|
||||||
|
work stoppage, computer failure or malfunction, or any and all
|
||||||
|
other commercial damages or losses), even if such Contributor
|
||||||
|
has been advised of the possibility of such damages.
|
||||||
|
|
||||||
|
9. Accepting Warranty or Additional Liability. While redistributing
|
||||||
|
the Work or Derivative Works thereof, You may choose to offer,
|
||||||
|
and charge a fee for, acceptance of support, warranty, indemnity,
|
||||||
|
or other liability obligations and/or rights consistent with this
|
||||||
|
License. However, in accepting such obligations, You may act only
|
||||||
|
on Your own behalf and on Your sole responsibility, not on behalf
|
||||||
|
of any other Contributor, and only if You agree to indemnify,
|
||||||
|
defend, and hold each Contributor harmless for any liability
|
||||||
|
incurred by, or claims asserted against, such Contributor by reason
|
||||||
|
of your accepting any such warranty or additional liability.
|
||||||
|
|
||||||
|
END OF TERMS AND CONDITIONS
|
||||||
|
|
||||||
|
APPENDIX: How to apply the Apache License to your work.
|
||||||
|
|
||||||
|
To apply the Apache License to your work, attach the following
|
||||||
|
boilerplate notice, with the fields enclosed by brackets "[]"
|
||||||
|
replaced with your own identifying information. (Don't include
|
||||||
|
the brackets!) The text should be enclosed in the appropriate
|
||||||
|
comment syntax for the file format. We also recommend that a
|
||||||
|
file or class name and description of purpose be included on the
|
||||||
|
same "printed page" as the copyright notice for easier
|
||||||
|
identification within third-party archives.
|
||||||
|
|
||||||
|
Copyright [yyyy] [name of copyright owner]
|
||||||
|
|
||||||
|
Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
you may not use this file except in compliance with the License.
|
||||||
|
You may obtain a copy of the License at
|
||||||
|
|
||||||
|
http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
|
||||||
|
Unless required by applicable law or agreed to in writing, software
|
||||||
|
distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
See the License for the specific language governing permissions and
|
||||||
|
limitations under the License.
|
||||||
|
|
||||||
|
|
||||||
|
--- LLVM Exceptions to the Apache 2.0 License ----
|
||||||
|
|
||||||
|
As an exception, if, as a result of your compiling your source code, portions
|
||||||
|
of this Software are embedded into an Object form of such source code, you
|
||||||
|
may redistribute such embedded portions in such Object form without complying
|
||||||
|
with the conditions of Sections 4(a), 4(b) and 4(d) of the License.
|
||||||
|
|
||||||
|
In addition, if you combine or link compiled forms of this Software with
|
||||||
|
software that is licensed under the GPLv2 ("Combined Software") and if a
|
||||||
|
court of competent jurisdiction determines that the patent provision (Section
|
||||||
|
3), the indemnity provision (Section 9) or other Section of the License
|
||||||
|
conflicts with the conditions of the GPLv2, you may retroactively and
|
||||||
|
prospectively choose to deem waived or otherwise exclude such Section(s) of
|
||||||
|
the License, but only in their entirety and only with respect to the Combined
|
||||||
|
Software.
|
||||||
202
licenses/third-party/ldbc/LICENSE
vendored
Normal file
202
licenses/third-party/ldbc/LICENSE
vendored
Normal file
@@ -0,0 +1,202 @@
|
|||||||
|
|
||||||
|
Apache License
|
||||||
|
Version 2.0, January 2004
|
||||||
|
http://www.apache.org/licenses/
|
||||||
|
|
||||||
|
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
|
||||||
|
|
||||||
|
1. Definitions.
|
||||||
|
|
||||||
|
"License" shall mean the terms and conditions for use, reproduction,
|
||||||
|
and distribution as defined by Sections 1 through 9 of this document.
|
||||||
|
|
||||||
|
"Licensor" shall mean the copyright owner or entity authorized by
|
||||||
|
the copyright owner that is granting the License.
|
||||||
|
|
||||||
|
"Legal Entity" shall mean the union of the acting entity and all
|
||||||
|
other entities that control, are controlled by, or are under common
|
||||||
|
control with that entity. For the purposes of this definition,
|
||||||
|
"control" means (i) the power, direct or indirect, to cause the
|
||||||
|
direction or management of such entity, whether by contract or
|
||||||
|
otherwise, or (ii) ownership of fifty percent (50%) or more of the
|
||||||
|
outstanding shares, or (iii) beneficial ownership of such entity.
|
||||||
|
|
||||||
|
"You" (or "Your") shall mean an individual or Legal Entity
|
||||||
|
exercising permissions granted by this License.
|
||||||
|
|
||||||
|
"Source" form shall mean the preferred form for making modifications,
|
||||||
|
including but not limited to software source code, documentation
|
||||||
|
source, and configuration files.
|
||||||
|
|
||||||
|
"Object" form shall mean any form resulting from mechanical
|
||||||
|
transformation or translation of a Source form, including but
|
||||||
|
not limited to compiled object code, generated documentation,
|
||||||
|
and conversions to other media types.
|
||||||
|
|
||||||
|
"Work" shall mean the work of authorship, whether in Source or
|
||||||
|
Object form, made available under the License, as indicated by a
|
||||||
|
copyright notice that is included in or attached to the work
|
||||||
|
(an example is provided in the Appendix below).
|
||||||
|
|
||||||
|
"Derivative Works" shall mean any work, whether in Source or Object
|
||||||
|
form, that is based on (or derived from) the Work and for which the
|
||||||
|
editorial revisions, annotations, elaborations, or other modifications
|
||||||
|
represent, as a whole, an original work of authorship. For the purposes
|
||||||
|
of this License, Derivative Works shall not include works that remain
|
||||||
|
separable from, or merely link (or bind by name) to the interfaces of,
|
||||||
|
the Work and Derivative Works thereof.
|
||||||
|
|
||||||
|
"Contribution" shall mean any work of authorship, including
|
||||||
|
the original version of the Work and any modifications or additions
|
||||||
|
to that Work or Derivative Works thereof, that is intentionally
|
||||||
|
submitted to Licensor for inclusion in the Work by the copyright owner
|
||||||
|
or by an individual or Legal Entity authorized to submit on behalf of
|
||||||
|
the copyright owner. For the purposes of this definition, "submitted"
|
||||||
|
means any form of electronic, verbal, or written communication sent
|
||||||
|
to the Licensor or its representatives, including but not limited to
|
||||||
|
communication on electronic mailing lists, source code control systems,
|
||||||
|
and issue tracking systems that are managed by, or on behalf of, the
|
||||||
|
Licensor for the purpose of discussing and improving the Work, but
|
||||||
|
excluding communication that is conspicuously marked or otherwise
|
||||||
|
designated in writing by the copyright owner as "Not a Contribution."
|
||||||
|
|
||||||
|
"Contributor" shall mean Licensor and any individual or Legal Entity
|
||||||
|
on behalf of whom a Contribution has been received by Licensor and
|
||||||
|
subsequently incorporated within the Work.
|
||||||
|
|
||||||
|
2. Grant of Copyright License. Subject to the terms and conditions of
|
||||||
|
this License, each Contributor hereby grants to You a perpetual,
|
||||||
|
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
|
||||||
|
copyright license to reproduce, prepare Derivative Works of,
|
||||||
|
publicly display, publicly perform, sublicense, and distribute the
|
||||||
|
Work and such Derivative Works in Source or Object form.
|
||||||
|
|
||||||
|
3. Grant of Patent License. Subject to the terms and conditions of
|
||||||
|
this License, each Contributor hereby grants to You a perpetual,
|
||||||
|
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
|
||||||
|
(except as stated in this section) patent license to make, have made,
|
||||||
|
use, offer to sell, sell, import, and otherwise transfer the Work,
|
||||||
|
where such license applies only to those patent claims licensable
|
||||||
|
by such Contributor that are necessarily infringed by their
|
||||||
|
Contribution(s) alone or by combination of their Contribution(s)
|
||||||
|
with the Work to which such Contribution(s) was submitted. If You
|
||||||
|
institute patent litigation against any entity (including a
|
||||||
|
cross-claim or counterclaim in a lawsuit) alleging that the Work
|
||||||
|
or a Contribution incorporated within the Work constitutes direct
|
||||||
|
or contributory patent infringement, then any patent licenses
|
||||||
|
granted to You under this License for that Work shall terminate
|
||||||
|
as of the date such litigation is filed.
|
||||||
|
|
||||||
|
4. Redistribution. You may reproduce and distribute copies of the
|
||||||
|
Work or Derivative Works thereof in any medium, with or without
|
||||||
|
modifications, and in Source or Object form, provided that You
|
||||||
|
meet the following conditions:
|
||||||
|
|
||||||
|
(a) You must give any other recipients of the Work or
|
||||||
|
Derivative Works a copy of this License; and
|
||||||
|
|
||||||
|
(b) You must cause any modified files to carry prominent notices
|
||||||
|
stating that You changed the files; and
|
||||||
|
|
||||||
|
(c) You must retain, in the Source form of any Derivative Works
|
||||||
|
that You distribute, all copyright, patent, trademark, and
|
||||||
|
attribution notices from the Source form of the Work,
|
||||||
|
excluding those notices that do not pertain to any part of
|
||||||
|
the Derivative Works; and
|
||||||
|
|
||||||
|
(d) If the Work includes a "NOTICE" text file as part of its
|
||||||
|
distribution, then any Derivative Works that You distribute must
|
||||||
|
include a readable copy of the attribution notices contained
|
||||||
|
within such NOTICE file, excluding those notices that do not
|
||||||
|
pertain to any part of the Derivative Works, in at least one
|
||||||
|
of the following places: within a NOTICE text file distributed
|
||||||
|
as part of the Derivative Works; within the Source form or
|
||||||
|
documentation, if provided along with the Derivative Works; or,
|
||||||
|
within a display generated by the Derivative Works, if and
|
||||||
|
wherever such third-party notices normally appear. The contents
|
||||||
|
of the NOTICE file are for informational purposes only and
|
||||||
|
do not modify the License. You may add Your own attribution
|
||||||
|
notices within Derivative Works that You distribute, alongside
|
||||||
|
or as an addendum to the NOTICE text from the Work, provided
|
||||||
|
that such additional attribution notices cannot be construed
|
||||||
|
as modifying the License.
|
||||||
|
|
||||||
|
You may add Your own copyright statement to Your modifications and
|
||||||
|
may provide additional or different license terms and conditions
|
||||||
|
for use, reproduction, or distribution of Your modifications, or
|
||||||
|
for any such Derivative Works as a whole, provided Your use,
|
||||||
|
reproduction, and distribution of the Work otherwise complies with
|
||||||
|
the conditions stated in this License.
|
||||||
|
|
||||||
|
5. Submission of Contributions. Unless You explicitly state otherwise,
|
||||||
|
any Contribution intentionally submitted for inclusion in the Work
|
||||||
|
by You to the Licensor shall be under the terms and conditions of
|
||||||
|
this License, without any additional terms or conditions.
|
||||||
|
Notwithstanding the above, nothing herein shall supersede or modify
|
||||||
|
the terms of any separate license agreement you may have executed
|
||||||
|
with Licensor regarding such Contributions.
|
||||||
|
|
||||||
|
6. Trademarks. This License does not grant permission to use the trade
|
||||||
|
names, trademarks, service marks, or product names of the Licensor,
|
||||||
|
except as required for reasonable and customary use in describing the
|
||||||
|
origin of the Work and reproducing the content of the NOTICE file.
|
||||||
|
|
||||||
|
7. Disclaimer of Warranty. Unless required by applicable law or
|
||||||
|
agreed to in writing, Licensor provides the Work (and each
|
||||||
|
Contributor provides its Contributions) on an "AS IS" BASIS,
|
||||||
|
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
|
||||||
|
implied, including, without limitation, any warranties or conditions
|
||||||
|
of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
|
||||||
|
PARTICULAR PURPOSE. You are solely responsible for determining the
|
||||||
|
appropriateness of using or redistributing the Work and assume any
|
||||||
|
risks associated with Your exercise of permissions under this License.
|
||||||
|
|
||||||
|
8. Limitation of Liability. In no event and under no legal theory,
|
||||||
|
whether in tort (including negligence), contract, or otherwise,
|
||||||
|
unless required by applicable law (such as deliberate and grossly
|
||||||
|
negligent acts) or agreed to in writing, shall any Contributor be
|
||||||
|
liable to You for damages, including any direct, indirect, special,
|
||||||
|
incidental, or consequential damages of any character arising as a
|
||||||
|
result of this License or out of the use or inability to use the
|
||||||
|
Work (including but not limited to damages for loss of goodwill,
|
||||||
|
work stoppage, computer failure or malfunction, or any and all
|
||||||
|
other commercial damages or losses), even if such Contributor
|
||||||
|
has been advised of the possibility of such damages.
|
||||||
|
|
||||||
|
9. Accepting Warranty or Additional Liability. While redistributing
|
||||||
|
the Work or Derivative Works thereof, You may choose to offer,
|
||||||
|
and charge a fee for, acceptance of support, warranty, indemnity,
|
||||||
|
or other liability obligations and/or rights consistent with this
|
||||||
|
License. However, in accepting such obligations, You may act only
|
||||||
|
on Your own behalf and on Your sole responsibility, not on behalf
|
||||||
|
of any other Contributor, and only if You agree to indemnify,
|
||||||
|
defend, and hold each Contributor harmless for any liability
|
||||||
|
incurred by, or claims asserted against, such Contributor by reason
|
||||||
|
of your accepting any such warranty or additional liability.
|
||||||
|
|
||||||
|
END OF TERMS AND CONDITIONS
|
||||||
|
|
||||||
|
APPENDIX: How to apply the Apache License to your work.
|
||||||
|
|
||||||
|
To apply the Apache License to your work, attach the following
|
||||||
|
boilerplate notice, with the fields enclosed by brackets "[]"
|
||||||
|
replaced with your own identifying information. (Don't include
|
||||||
|
the brackets!) The text should be enclosed in the appropriate
|
||||||
|
comment syntax for the file format. We also recommend that a
|
||||||
|
file or class name and description of purpose be included on the
|
||||||
|
same "printed page" as the copyright notice for easier
|
||||||
|
identification within third-party archives.
|
||||||
|
|
||||||
|
Copyright [yyyy] [name of copyright owner]
|
||||||
|
|
||||||
|
Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
you may not use this file except in compliance with the License.
|
||||||
|
You may obtain a copy of the License at
|
||||||
|
|
||||||
|
http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
|
||||||
|
Unless required by applicable law or agreed to in writing, software
|
||||||
|
distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
See the License for the specific language governing permissions and
|
||||||
|
limitations under the License.
|
||||||
@@ -1,4 +1,4 @@
|
|||||||
// Copyright 2022 Memgraph Ltd.
|
// Copyright 2023 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,11 @@ void ProcImpl(std::vector<mgp::Value> arguments, mgp::Graph graph, mgp::RecordFa
|
|||||||
|
|
||||||
void SampleReadProc(mgp_list *args, mgp_graph *memgraph_graph, mgp_result *result, mgp_memory *memory) {
|
void SampleReadProc(mgp_list *args, mgp_graph *memgraph_graph, mgp_result *result, mgp_memory *memory) {
|
||||||
try {
|
try {
|
||||||
mgp::memory = memory;
|
// The outcommented way of assigning the memory pointer is still
|
||||||
|
// working, but it is deprecated because of certain concurrency
|
||||||
|
// issues. Please use the guard instead.
|
||||||
|
// mgp::memory = memory;
|
||||||
|
mgp::MemoryDispatcherGuard guard(memory);
|
||||||
|
|
||||||
std::vector<mgp::Value> arguments;
|
std::vector<mgp::Value> arguments;
|
||||||
for (size_t i = 0; i < mgp::list_size(args); i++) {
|
for (size_t i = 0; i < mgp::list_size(args); i++) {
|
||||||
@@ -34,7 +38,11 @@ void SampleReadProc(mgp_list *args, mgp_graph *memgraph_graph, mgp_result *resul
|
|||||||
}
|
}
|
||||||
|
|
||||||
void AddXNodes(mgp_list *args, mgp_graph *memgraph_graph, mgp_result *result, mgp_memory *memory) {
|
void AddXNodes(mgp_list *args, mgp_graph *memgraph_graph, mgp_result *result, mgp_memory *memory) {
|
||||||
mgp::memory = memory;
|
// The outcommented way of assigning the memory pointer is still
|
||||||
|
// working, but it is deprecated because of certain concurrency
|
||||||
|
// issues. Please use the guard instead.
|
||||||
|
// mgp::memory = memory;
|
||||||
|
mgp::MemoryDispatcherGuard guard(memory);
|
||||||
auto graph = mgp::Graph(memgraph_graph);
|
auto graph = mgp::Graph(memgraph_graph);
|
||||||
|
|
||||||
std::vector<mgp::Value> arguments;
|
std::vector<mgp::Value> arguments;
|
||||||
@@ -49,7 +57,11 @@ void AddXNodes(mgp_list *args, mgp_graph *memgraph_graph, mgp_result *result, mg
|
|||||||
}
|
}
|
||||||
|
|
||||||
void Multiply(mgp_list *args, mgp_func_context *ctx, mgp_func_result *res, mgp_memory *memory) {
|
void Multiply(mgp_list *args, mgp_func_context *ctx, mgp_func_result *res, mgp_memory *memory) {
|
||||||
mgp::memory = memory;
|
// The outcommented way of assigning the memory pointer is still
|
||||||
|
// working, but it is deprecated because of certain concurrency
|
||||||
|
// issues. Please use the guard instead.
|
||||||
|
// mgp::memory = memory;
|
||||||
|
mgp::MemoryDispatcherGuard guard(memory);
|
||||||
|
|
||||||
std::vector<mgp::Value> arguments;
|
std::vector<mgp::Value> arguments;
|
||||||
for (size_t i = 0; i < mgp::list_size(args); i++) {
|
for (size_t i = 0; i < mgp::list_size(args); i++) {
|
||||||
@@ -67,7 +79,11 @@ void Multiply(mgp_list *args, mgp_func_context *ctx, mgp_func_result *res, mgp_m
|
|||||||
|
|
||||||
extern "C" int mgp_init_module(struct mgp_module *module, struct mgp_memory *memory) {
|
extern "C" int mgp_init_module(struct mgp_module *module, struct mgp_memory *memory) {
|
||||||
try {
|
try {
|
||||||
mgp::memory = memory;
|
// The outcommented way of assigning the memory pointer is still
|
||||||
|
// working, but it is deprecated because of certain concurrency
|
||||||
|
// issues. Please use the guard instead.
|
||||||
|
// mgp::memory = memory;
|
||||||
|
mgp::MemoryDispatcherGuard guard(memory);
|
||||||
|
|
||||||
AddProcedure(SampleReadProc, "return_true", mgp::ProcedureType::Read,
|
AddProcedure(SampleReadProc, "return_true", mgp::ProcedureType::Read,
|
||||||
{mgp::Parameter("param_1", mgp::Type::Int), mgp::Parameter("param_2", mgp::Type::Double, 2.3)},
|
{mgp::Parameter("param_1", mgp::Type::Int), mgp::Parameter("param_2", mgp::Type::Double, 2.3)},
|
||||||
@@ -77,7 +93,11 @@ extern "C" int mgp_init_module(struct mgp_module *module, struct mgp_memory *mem
|
|||||||
}
|
}
|
||||||
|
|
||||||
try {
|
try {
|
||||||
mgp::memory = memory;
|
// The outcommented way of assigning the memory pointer is still
|
||||||
|
// working, but it is deprecated because of certain concurrency
|
||||||
|
// issues. Please use the guard instead.
|
||||||
|
// mgp::memory = memory;
|
||||||
|
mgp::MemoryDispatcherGuard guard(memory);
|
||||||
|
|
||||||
mgp::AddProcedure(AddXNodes, "add_x_nodes", mgp::ProcedureType::Write, {mgp::Parameter("param_1", mgp::Type::Int)},
|
mgp::AddProcedure(AddXNodes, "add_x_nodes", mgp::ProcedureType::Write, {mgp::Parameter("param_1", mgp::Type::Int)},
|
||||||
{}, module, memory);
|
{}, module, memory);
|
||||||
@@ -87,7 +107,11 @@ extern "C" int mgp_init_module(struct mgp_module *module, struct mgp_memory *mem
|
|||||||
}
|
}
|
||||||
|
|
||||||
try {
|
try {
|
||||||
mgp::memory = memory;
|
// The outcommented way of assigning the memory pointer is still
|
||||||
|
// working, but it is deprecated because of certain concurrency
|
||||||
|
// issues. Please use the guard instead.
|
||||||
|
// mgp::memory = memory;
|
||||||
|
mgp::MemoryDispatcherGuard guard(memory);
|
||||||
|
|
||||||
mgp::AddFunction(Multiply, "multiply",
|
mgp::AddFunction(Multiply, "multiply",
|
||||||
{mgp::Parameter("int", mgp::Type::Int), mgp::Parameter("int", mgp::Type::Int, (int64_t)3)}, module,
|
{mgp::Parameter("int", mgp::Type::Int), mgp::Parameter("int", mgp::Type::Int, (int64_t)3)}, module,
|
||||||
|
|||||||
@@ -1,6 +1,10 @@
|
|||||||
# Install systemd service (must use absolute path).
|
# Install systemd service (must use absolute path).
|
||||||
install(FILES ${CMAKE_CURRENT_SOURCE_DIR}/memgraph.service
|
install(FILES ${CMAKE_CURRENT_SOURCE_DIR}/memgraph.service
|
||||||
DESTINATION /lib/systemd/system)
|
DESTINATION /lib/systemd/system)
|
||||||
|
|
||||||
|
# Set parameters to recognize the host distro
|
||||||
|
cmake_host_system_information(RESULT DISTRO QUERY DISTRIB_NAME)
|
||||||
|
cmake_host_system_information(RESULT DISTRO_VERSION QUERY DISTRIB_VERSION)
|
||||||
|
|
||||||
# ---- Setup CPack --------
|
# ---- Setup CPack --------
|
||||||
|
|
||||||
@@ -10,12 +14,13 @@ 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
|
# Setting architecture extension for deb packages
|
||||||
set(MG_ARCH_EXTENSION_DEB "all")
|
set(MG_ARCH_EXTENSION_DEB "all")
|
||||||
if (${MG_ARCH} STREQUAL "x86_64")
|
|
||||||
|
if(${MG_ARCH} STREQUAL "x86_64")
|
||||||
set(MG_ARCH_EXTENSION_DEB "amd64")
|
set(MG_ARCH_EXTENSION_DEB "amd64")
|
||||||
elseif (${MG_ARCH} STREQUAL "ARM64")
|
elseif(${MG_ARCH} STREQUAL "ARM64")
|
||||||
set(MG_ARCH_EXTENSION_DEB "arm64")
|
set(MG_ARCH_EXTENSION_DEB "arm64")
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
# DEB specific
|
# DEB specific
|
||||||
@@ -34,21 +39,24 @@ set(CPACK_DEBIAN_PACKAGE_CONTROL_EXTRA
|
|||||||
"${CMAKE_CURRENT_SOURCE_DIR}/debian/postrm;"
|
"${CMAKE_CURRENT_SOURCE_DIR}/debian/postrm;"
|
||||||
"${CMAKE_CURRENT_SOURCE_DIR}/debian/postinst;")
|
"${CMAKE_CURRENT_SOURCE_DIR}/debian/postinst;")
|
||||||
set(CPACK_DEBIAN_PACKAGE_SHLIBDEPS ON)
|
set(CPACK_DEBIAN_PACKAGE_SHLIBDEPS ON)
|
||||||
|
|
||||||
# Description formatting is important, summary must be followed with a newline and 1 space.
|
# Description formatting is important, summary must be followed with a newline and 1 space.
|
||||||
set(CPACK_DEBIAN_PACKAGE_DESCRIPTION "${CPACK_PACKAGE_DESCRIPTION_SUMMARY}
|
set(CPACK_DEBIAN_PACKAGE_DESCRIPTION "${CPACK_PACKAGE_DESCRIPTION_SUMMARY}
|
||||||
Contains Memgraph, the graph database. It aims to deliver developers the
|
Contains Memgraph, the graph database. It aims to deliver developers the
|
||||||
speed, simplicity and scale required to build the next generation of
|
speed, simplicity and scale required to build the next generation of
|
||||||
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
|
# Setting architecture extension for rpm packages
|
||||||
set(MG_ARCH_EXTENSION_RPM "noarch")
|
set(MG_ARCH_EXTENSION_RPM "noarch")
|
||||||
if (${MG_ARCH} STREQUAL "x86_64")
|
|
||||||
|
if(${MG_ARCH} STREQUAL "x86_64")
|
||||||
set(MG_ARCH_EXTENSION_RPM "x86_64")
|
set(MG_ARCH_EXTENSION_RPM "x86_64")
|
||||||
elseif (${MG_ARCH} STREQUAL "ARM64")
|
elseif(${MG_ARCH} STREQUAL "ARM64")
|
||||||
set(MG_ARCH_EXTENSION_RPM "aarch64")
|
set(MG_ARCH_EXTENSION_RPM "aarch64")
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
# RPM specific
|
# RPM specific
|
||||||
@@ -56,18 +64,26 @@ 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}.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)
|
||||||
set(CPACK_RPM_PACKAGE_REQUIRES_PRE "shadow-utils")
|
set(CPACK_RPM_PACKAGE_REQUIRES_PRE "shadow-utils")
|
||||||
set(CPACK_RPM_USER_BINARY_SPECFILE "${CMAKE_CURRENT_SOURCE_DIR}/rpm/memgraph.spec.in")
|
set(CPACK_RPM_USER_BINARY_SPECFILE "${CMAKE_CURRENT_SOURCE_DIR}/rpm/memgraph.spec.in")
|
||||||
set(CPACK_RPM_PACKAGE_LICENSE "Memgraph License")
|
set(CPACK_RPM_PACKAGE_LICENSE "Memgraph License")
|
||||||
|
# CPACK deduces dependency to libstdc++ which:
|
||||||
|
# * can't be easily installed on Centos 7 (the one from the toolchain,
|
||||||
|
# only required to avoid printing issue within query modules)
|
||||||
|
# * it causes issues with glibcxx 2.4
|
||||||
|
# `if(DISTRO STREQUAL "Amazon Linux" AND DISTRO_VERSION STREQUAL "2")`
|
||||||
|
set(CPACK_RPM_PACKAGE_AUTOREQ " no")
|
||||||
|
|
||||||
# Description formatting is important, no line must be greater than 80 characters.
|
# Description formatting is important, no line must be greater than 80 characters.
|
||||||
set(CPACK_RPM_PACKAGE_DESCRIPTION "Contains Memgraph, the graph database.
|
set(CPACK_RPM_PACKAGE_DESCRIPTION "Contains Memgraph, the graph database.
|
||||||
It aims to deliver developers the speed, simplicity and scale required to build
|
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, logrotate")
|
||||||
|
|
||||||
# All variables must be set before including.
|
# All variables must be set before including.
|
||||||
include(CPack)
|
include(CPack)
|
||||||
|
|||||||
@@ -55,7 +55,8 @@ 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} \
|
# NOTE: --pull is here to always pull that latest base image because of security patches.
|
||||||
|
docker build --pull -t ${image_name} ${tag_latest} -f ${dockerfile_path} \
|
||||||
--build-arg BINARY_NAME=${package_name} \
|
--build-arg BINARY_NAME=${package_name} \
|
||||||
--build-arg EXTENSION=${extension} \
|
--build-arg EXTENSION=${extension} \
|
||||||
--build-arg TARGETARCH="" .
|
--build-arg TARGETARCH="" .
|
||||||
|
|||||||
15
release/package/amzn-2/Dockerfile
Normal file
15
release/package/amzn-2/Dockerfile
Normal file
@@ -0,0 +1,15 @@
|
|||||||
|
FROM amazonlinux:2
|
||||||
|
|
||||||
|
ARG TOOLCHAIN_VERSION
|
||||||
|
|
||||||
|
RUN yum -y update \
|
||||||
|
&& yum install -y wget git tar
|
||||||
|
# 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-amzn-2-x86_64.tar.gz \
|
||||||
|
-O ${TOOLCHAIN_VERSION}-binaries-amzn-2-x86_64.tar.gz \
|
||||||
|
&& tar xzvf ${TOOLCHAIN_VERSION}-binaries-amzn-2-x86_64.tar.gz -C /opt \
|
||||||
|
&& rm ${TOOLCHAIN_VERSION}-binaries-amzn-2-x86_64.tar.gz
|
||||||
|
|
||||||
|
ENTRYPOINT ["sleep", "infinity"]
|
||||||
@@ -9,6 +9,7 @@ RUN yum -y update \
|
|||||||
|
|
||||||
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-x86_64.tar.gz \
|
||||||
-O ${TOOLCHAIN_VERSION}-binaries-centos-7-x86_64.tar.gz \
|
-O ${TOOLCHAIN_VERSION}-binaries-centos-7-x86_64.tar.gz \
|
||||||
&& tar xzvf ${TOOLCHAIN_VERSION}-binaries-centos-7-x86_64.tar.gz -C /opt
|
&& tar xzvf ${TOOLCHAIN_VERSION}-binaries-centos-7-x86_64.tar.gz -C /opt \
|
||||||
|
&& rm ${TOOLCHAIN_VERSION}-binaries-centos-7-x86_64.tar.gz
|
||||||
|
|
||||||
ENTRYPOINT ["sleep", "infinity"]
|
ENTRYPOINT ["sleep", "infinity"]
|
||||||
|
|||||||
@@ -9,6 +9,7 @@ RUN yum -y update \
|
|||||||
|
|
||||||
RUN wget -q https://s3-eu-west-1.amazonaws.com/deps.memgraph.io/${TOOLCHAIN_VERSION}/${TOOLCHAIN_VERSION}-binaries-centos-9-x86_64.tar.gz \
|
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 \
|
-O ${TOOLCHAIN_VERSION}-binaries-centos-9-x86_64.tar.gz \
|
||||||
&& tar xzvf ${TOOLCHAIN_VERSION}-binaries-centos-9-x86_64.tar.gz -C /opt
|
&& tar xzvf ${TOOLCHAIN_VERSION}-binaries-centos-9-x86_64.tar.gz -C /opt \
|
||||||
|
&& rm ${TOOLCHAIN_VERSION}-binaries-centos-9-x86_64.tar.gz
|
||||||
|
|
||||||
ENTRYPOINT ["sleep", "infinity"]
|
ENTRYPOINT ["sleep", "infinity"]
|
||||||
|
|||||||
@@ -12,6 +12,7 @@ RUN apt update && apt install -y \
|
|||||||
|
|
||||||
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-amd64.tar.gz \
|
||||||
-O ${TOOLCHAIN_VERSION}-binaries-debian-10-amd64.tar.gz \
|
-O ${TOOLCHAIN_VERSION}-binaries-debian-10-amd64.tar.gz \
|
||||||
&& tar xzvf ${TOOLCHAIN_VERSION}-binaries-debian-10-amd64.tar.gz -C /opt
|
&& tar xzvf ${TOOLCHAIN_VERSION}-binaries-debian-10-amd64.tar.gz -C /opt \
|
||||||
|
&& rm ${TOOLCHAIN_VERSION}-binaries-debian-10-amd64.tar.gz
|
||||||
|
|
||||||
ENTRYPOINT ["sleep", "infinity"]
|
ENTRYPOINT ["sleep", "infinity"]
|
||||||
|
|||||||
@@ -12,6 +12,7 @@ RUN apt update && apt install -y \
|
|||||||
|
|
||||||
RUN wget -q https://s3-eu-west-1.amazonaws.com/deps.memgraph.io/${TOOLCHAIN_VERSION}/${TOOLCHAIN_VERSION}-binaries-debian-11-arm64.tar.gz \
|
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 \
|
-O ${TOOLCHAIN_VERSION}-binaries-debian-11-arm64.tar.gz \
|
||||||
&& tar xzvf ${TOOLCHAIN_VERSION}-binaries-debian-11-arm64.tar.gz -C /opt
|
&& tar xzvf ${TOOLCHAIN_VERSION}-binaries-debian-11-arm64.tar.gz -C /opt \
|
||||||
|
&& rm ${TOOLCHAIN_VERSION}-binaries-debian-11-arm64.tar.gz
|
||||||
|
|
||||||
ENTRYPOINT ["sleep", "infinity"]
|
ENTRYPOINT ["sleep", "infinity"]
|
||||||
|
|||||||
@@ -12,6 +12,7 @@ RUN apt update && apt install -y \
|
|||||||
|
|
||||||
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-amd64.tar.gz \
|
||||||
-O ${TOOLCHAIN_VERSION}-binaries-debian-11-amd64.tar.gz \
|
-O ${TOOLCHAIN_VERSION}-binaries-debian-11-amd64.tar.gz \
|
||||||
&& tar xzvf ${TOOLCHAIN_VERSION}-binaries-debian-11-amd64.tar.gz -C /opt
|
&& tar xzvf ${TOOLCHAIN_VERSION}-binaries-debian-11-amd64.tar.gz -C /opt \
|
||||||
|
&& rm ${TOOLCHAIN_VERSION}-binaries-debian-11-amd64.tar.gz
|
||||||
|
|
||||||
ENTRYPOINT ["sleep", "infinity"]
|
ENTRYPOINT ["sleep", "infinity"]
|
||||||
|
|||||||
@@ -32,3 +32,7 @@ services:
|
|||||||
build:
|
build:
|
||||||
context: fedora-36
|
context: fedora-36
|
||||||
container_name: "mgbuild_fedora-36"
|
container_name: "mgbuild_fedora-36"
|
||||||
|
mgbuild_amzn-2:
|
||||||
|
build:
|
||||||
|
context: amzn-2
|
||||||
|
container_name: "mgbuild_amzn-2"
|
||||||
|
|||||||
@@ -10,6 +10,7 @@ RUN yum -y update \
|
|||||||
|
|
||||||
RUN wget -q https://s3-eu-west-1.amazonaws.com/deps.memgraph.io/${TOOLCHAIN_VERSION}/${TOOLCHAIN_VERSION}-binaries-fedora-36-x86_64.tar.gz \
|
RUN wget -q https://s3-eu-west-1.amazonaws.com/deps.memgraph.io/${TOOLCHAIN_VERSION}/${TOOLCHAIN_VERSION}-binaries-fedora-36-x86_64.tar.gz \
|
||||||
-O ${TOOLCHAIN_VERSION}-binaries-fedora-36-x86_64.tar.gz \
|
-O ${TOOLCHAIN_VERSION}-binaries-fedora-36-x86_64.tar.gz \
|
||||||
&& tar xzvf ${TOOLCHAIN_VERSION}-binaries-fedora-36-x86_64.tar.gz -C /opt
|
&& tar xzvf ${TOOLCHAIN_VERSION}-binaries-fedora-36-x86_64.tar.gz -C /opt \
|
||||||
|
&& rm ${TOOLCHAIN_VERSION}-binaries-fedora-36-x86_64.tar.gz
|
||||||
|
|
||||||
ENTRYPOINT ["sleep", "infinity"]
|
ENTRYPOINT ["sleep", "infinity"]
|
||||||
|
|||||||
@@ -3,14 +3,22 @@
|
|||||||
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 fedora-36 ubuntu-22.04-arm)
|
SUPPORTED_OS=(
|
||||||
|
centos-7 centos-9
|
||||||
|
debian-10 debian-11 debian-11-arm
|
||||||
|
ubuntu-18.04 ubuntu-20.04 ubuntu-22.04 ubuntu-22.04-arm
|
||||||
|
fedora-36
|
||||||
|
amzn-2
|
||||||
|
)
|
||||||
|
|
||||||
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"
|
||||||
HOST_OUTPUT_DIR="$PROJECT_ROOT/build/output"
|
HOST_OUTPUT_DIR="$PROJECT_ROOT/build/output"
|
||||||
|
|
||||||
print_help () {
|
print_help () {
|
||||||
echo "$0 init|package {os} [--for-docker|--for-platform]|docker|test"
|
# TODO(gitbuda): Update the release/package/run.sh help
|
||||||
|
echo "$0 init|package|docker|test {os} [--for-docker|--for-platform]"
|
||||||
echo ""
|
echo ""
|
||||||
echo " OSs: ${SUPPORTED_OS[*]}"
|
echo " OSs: ${SUPPORTED_OS[*]}"
|
||||||
exit 1
|
exit 1
|
||||||
@@ -23,12 +31,12 @@ make_package () {
|
|||||||
echo "Building Memgraph for $os on $build_container..."
|
echo "Building Memgraph for $os on $build_container..."
|
||||||
|
|
||||||
package_command=""
|
package_command=""
|
||||||
if [[ "$os" =~ ^"centos".* ]] || [[ "$os" =~ ^"fedora".* ]]; then
|
if [[ "$os" =~ ^"centos".* ]] || [[ "$os" =~ ^"fedora".* ]] || [[ "$os" =~ ^"amzn".* ]]; then
|
||||||
docker exec "$build_container" bash -c "yum -y update"
|
docker exec "$build_container" bash -c "yum -y update"
|
||||||
package_command=" cpack -G RPM --config ../CPackConfig.cmake && rpmlint --file='../../release/rpm/rpmlintrc' memgraph*.rpm "
|
package_command=" cpack -G RPM --config ../CPackConfig.cmake && rpmlint --file='../../release/rpm/rpmlintrc' memgraph*.rpm "
|
||||||
fi
|
fi
|
||||||
if [[ "$os" =~ ^"debian".* ]]; then
|
if [[ "$os" =~ ^"debian".* ]]; then
|
||||||
docker exec "$build_container" bash -c "apt update"
|
docker exec "$build_container" bash -c "apt --allow-releaseinfo-change -y update"
|
||||||
package_command=" cpack -G DEB --config ../CPackConfig.cmake "
|
package_command=" cpack -G DEB --config ../CPackConfig.cmake "
|
||||||
fi
|
fi
|
||||||
if [[ "$os" =~ ^"ubuntu".* ]]; then
|
if [[ "$os" =~ ^"ubuntu".* ]]; then
|
||||||
@@ -57,6 +65,7 @@ make_package () {
|
|||||||
git fetch origin master:master
|
git fetch origin master:master
|
||||||
fi
|
fi
|
||||||
docker exec "$build_container" mkdir -p /memgraph
|
docker exec "$build_container" mkdir -p /memgraph
|
||||||
|
# TODO(gitbuda): Revisit copying the whole repo -> makese sense under CI.
|
||||||
docker cp "$PROJECT_ROOT/." "$build_container:/memgraph/"
|
docker cp "$PROJECT_ROOT/." "$build_container:/memgraph/"
|
||||||
|
|
||||||
container_build_dir="/memgraph/build"
|
container_build_dir="/memgraph/build"
|
||||||
@@ -67,6 +76,8 @@ 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.
|
||||||
|
# TODO(gitbuda): On the other side, having this here allows updating deps
|
||||||
|
# wihout reruning the build containers.
|
||||||
echo "Installing dependencies using '/memgraph/environment/os/$os.sh' script..."
|
echo "Installing dependencies using '/memgraph/environment/os/$os.sh' script..."
|
||||||
docker exec "$build_container" bash -c "/memgraph/environment/os/$os.sh install TOOLCHAIN_RUN_DEPS"
|
docker exec "$build_container" bash -c "/memgraph/environment/os/$os.sh install 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"
|
||||||
@@ -76,6 +87,7 @@ make_package () {
|
|||||||
docker exec "$build_container" bash -c "cd /memgraph && git config --global --add safe.directory '*'"
|
docker exec "$build_container" bash -c "cd /memgraph && git config --global --add safe.directory '*'"
|
||||||
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 ./*"
|
||||||
|
# TODO(gitbuda): cmake fails locally if remote is clone via ssh because of the key -> FIX
|
||||||
if [[ "$os" =~ "-arm" ]]; then
|
if [[ "$os" =~ "-arm" ]]; then
|
||||||
docker exec "$build_container" bash -c "cd $container_build_dir && $ACTIVATE_TOOLCHAIN && cmake -DCMAKE_BUILD_TYPE=release -DMG_ARCH="ARM64" $telemetry_id_override_flag .."
|
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
|
else
|
||||||
@@ -101,8 +113,13 @@ make_package () {
|
|||||||
case "$1" in
|
case "$1" in
|
||||||
init)
|
init)
|
||||||
cd "$SCRIPT_DIR"
|
cd "$SCRIPT_DIR"
|
||||||
docker-compose build --build-arg TOOLCHAIN_VERSION="${TOOLCHAIN_VERSION}"
|
if ! which "docker-compose" >/dev/null; then
|
||||||
docker-compose up -d
|
docker_compose_cmd="docker compose"
|
||||||
|
else
|
||||||
|
docker_compose_cmd="docker-compose"
|
||||||
|
fi
|
||||||
|
$docker_compose_cmd build --build-arg TOOLCHAIN_VERSION="${TOOLCHAIN_VERSION}"
|
||||||
|
$docker_compose_cmd up -d
|
||||||
;;
|
;;
|
||||||
|
|
||||||
docker)
|
docker)
|
||||||
@@ -142,6 +159,19 @@ case "$1" in
|
|||||||
fi
|
fi
|
||||||
;;
|
;;
|
||||||
|
|
||||||
|
build)
|
||||||
|
shift 1
|
||||||
|
if [[ "$#" -ne 2 ]]; then
|
||||||
|
print_help
|
||||||
|
fi
|
||||||
|
# in the vX format, e.g. v5
|
||||||
|
toolchain_version="$1"
|
||||||
|
# a name of the os folder, e.g. ubuntu-22.04-arm
|
||||||
|
os="$2"
|
||||||
|
cd "$SCRIPT_DIR/$os"
|
||||||
|
docker build -f Dockerfile --build-arg TOOLCHAIN_VERSION="toolchain-$toolchain_version" -t "memgraph/memgraph-builder:${toolchain_version}_$os" .
|
||||||
|
;;
|
||||||
|
|
||||||
test)
|
test)
|
||||||
echo "TODO(gitbuda): Test all packages on mgtest containers."
|
echo "TODO(gitbuda): Test all packages on mgtest containers."
|
||||||
;;
|
;;
|
||||||
|
|||||||
@@ -12,6 +12,7 @@ RUN apt update && apt install -y \
|
|||||||
|
|
||||||
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-amd64.tar.gz \
|
||||||
-O ${TOOLCHAIN_VERSION}-binaries-ubuntu-18.04-amd64.tar.gz \
|
-O ${TOOLCHAIN_VERSION}-binaries-ubuntu-18.04-amd64.tar.gz \
|
||||||
&& tar xzvf ${TOOLCHAIN_VERSION}-binaries-ubuntu-18.04-amd64.tar.gz -C /opt
|
&& tar xzvf ${TOOLCHAIN_VERSION}-binaries-ubuntu-18.04-amd64.tar.gz -C /opt \
|
||||||
|
&& rm ${TOOLCHAIN_VERSION}-binaries-ubuntu-18.04-amd64.tar.gz
|
||||||
|
|
||||||
ENTRYPOINT ["sleep", "infinity"]
|
ENTRYPOINT ["sleep", "infinity"]
|
||||||
|
|||||||
@@ -12,6 +12,7 @@ RUN apt update && apt install -y \
|
|||||||
|
|
||||||
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-amd64.tar.gz \
|
||||||
-O ${TOOLCHAIN_VERSION}-binaries-ubuntu-20.04-amd64.tar.gz \
|
-O ${TOOLCHAIN_VERSION}-binaries-ubuntu-20.04-amd64.tar.gz \
|
||||||
&& tar xzvf ${TOOLCHAIN_VERSION}-binaries-ubuntu-20.04-amd64.tar.gz -C /opt
|
&& tar xzvf ${TOOLCHAIN_VERSION}-binaries-ubuntu-20.04-amd64.tar.gz -C /opt \
|
||||||
|
&& rm ${TOOLCHAIN_VERSION}-binaries-ubuntu-20.04-amd64.tar.gz
|
||||||
|
|
||||||
ENTRYPOINT ["sleep", "infinity"]
|
ENTRYPOINT ["sleep", "infinity"]
|
||||||
|
|||||||
@@ -12,6 +12,7 @@ RUN apt update && apt install -y \
|
|||||||
|
|
||||||
RUN wget -q https://s3-eu-west-1.amazonaws.com/deps.memgraph.io/${TOOLCHAIN_VERSION}/${TOOLCHAIN_VERSION}-binaries-ubuntu-22.04-arm64.tar.gz \
|
RUN wget -q https://s3-eu-west-1.amazonaws.com/deps.memgraph.io/${TOOLCHAIN_VERSION}/${TOOLCHAIN_VERSION}-binaries-ubuntu-22.04-arm64.tar.gz \
|
||||||
-O ${TOOLCHAIN_VERSION}-binaries-ubuntu-22.04-arm64.tar.gz \
|
-O ${TOOLCHAIN_VERSION}-binaries-ubuntu-22.04-arm64.tar.gz \
|
||||||
&& tar xzvf ${TOOLCHAIN_VERSION}-binaries-ubuntu-22.04-arm64.tar.gz -C /opt
|
&& tar xzvf ${TOOLCHAIN_VERSION}-binaries-ubuntu-22.04-arm64.tar.gz -C /opt \
|
||||||
|
&& rm ${TOOLCHAIN_VERSION}-binaries-ubuntu-22.04-arm64.tar.gz
|
||||||
|
|
||||||
ENTRYPOINT ["sleep", "infinity"]
|
ENTRYPOINT ["sleep", "infinity"]
|
||||||
|
|||||||
@@ -12,6 +12,7 @@ RUN apt update && apt install -y \
|
|||||||
|
|
||||||
RUN wget -q https://s3-eu-west-1.amazonaws.com/deps.memgraph.io/${TOOLCHAIN_VERSION}/${TOOLCHAIN_VERSION}-binaries-ubuntu-22.04-amd64.tar.gz \
|
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 \
|
-O ${TOOLCHAIN_VERSION}-binaries-ubuntu-22.04-amd64.tar.gz \
|
||||||
&& tar xzvf ${TOOLCHAIN_VERSION}-binaries-ubuntu-22.04-amd64.tar.gz -C /opt
|
&& tar xzvf ${TOOLCHAIN_VERSION}-binaries-ubuntu-22.04-amd64.tar.gz -C /opt \
|
||||||
|
&& rm ${TOOLCHAIN_VERSION}-binaries-ubuntu-22.04-amd64.tar.gz
|
||||||
|
|
||||||
ENTRYPOINT ["sleep", "infinity"]
|
ENTRYPOINT ["sleep", "infinity"]
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
# CMake configuration for the main memgraph library and executable
|
# CMake configuration for the main memgraph library and executable
|
||||||
|
|
||||||
# add memgraph sub libraries, ordered by dependency
|
# add memgraph sub libraries, ordered by dependency
|
||||||
add_subdirectory(lisp)
|
add_subdirectory(csv)
|
||||||
add_subdirectory(utils)
|
add_subdirectory(utils)
|
||||||
add_subdirectory(requests)
|
add_subdirectory(requests)
|
||||||
add_subdirectory(io)
|
add_subdirectory(io)
|
||||||
@@ -17,10 +17,7 @@ add_subdirectory(slk)
|
|||||||
add_subdirectory(rpc)
|
add_subdirectory(rpc)
|
||||||
add_subdirectory(license)
|
add_subdirectory(license)
|
||||||
add_subdirectory(auth)
|
add_subdirectory(auth)
|
||||||
|
add_subdirectory(audit)
|
||||||
if(MG_ENTERPRISE)
|
|
||||||
add_subdirectory(audit)
|
|
||||||
endif()
|
|
||||||
|
|
||||||
string(TOLOWER ${CMAKE_BUILD_TYPE} lower_build_type)
|
string(TOLOWER ${CMAKE_BUILD_TYPE} lower_build_type)
|
||||||
|
|
||||||
@@ -34,20 +31,19 @@ include_directories(${CMAKE_CURRENT_BINARY_DIR})
|
|||||||
# ----------------------------------------------------------------------------
|
# ----------------------------------------------------------------------------
|
||||||
set(mg_single_node_v2_sources
|
set(mg_single_node_v2_sources
|
||||||
memgraph.cpp
|
memgraph.cpp
|
||||||
|
flags/isolation_level.cpp
|
||||||
|
flags/memory_limit.cpp
|
||||||
|
flags/log_level.cpp
|
||||||
|
flags/general.cpp
|
||||||
|
flags/audit.cpp
|
||||||
|
flags/bolt.cpp
|
||||||
)
|
)
|
||||||
|
|
||||||
set(mg_single_node_v2_libs stdc++fs Threads::Threads
|
|
||||||
mg-telemetry mg-query mg-communication mg-memory mg-utils mg-auth mg-license mg-settings mg-glue)
|
|
||||||
|
|
||||||
if(MG_ENTERPRISE)
|
|
||||||
# These are enterprise subsystems
|
|
||||||
set(mg_single_node_v2_libs ${mg_single_node_v2_libs} mg-audit)
|
|
||||||
endif()
|
|
||||||
|
|
||||||
# memgraph main executable
|
# memgraph main executable
|
||||||
add_executable(memgraph ${mg_single_node_v2_sources})
|
add_executable(memgraph ${mg_single_node_v2_sources})
|
||||||
target_include_directories(memgraph PUBLIC ${CMAKE_SOURCE_DIR}/include)
|
target_include_directories(memgraph PUBLIC ${CMAKE_SOURCE_DIR}/include)
|
||||||
target_link_libraries(memgraph ${mg_single_node_v2_libs})
|
target_link_libraries(memgraph stdc++fs Threads::Threads
|
||||||
|
mg-telemetry mg-communication mg-memory mg-utils mg-license mg-settings mg-glue)
|
||||||
|
|
||||||
# NOTE: `include/mg_procedure.syms` describes a pattern match for symbols which
|
# NOTE: `include/mg_procedure.syms` describes a pattern match for symbols which
|
||||||
# should be dynamically exported, so that `dlopen` can correctly link the
|
# should be dynamically exported, so that `dlopen` can correctly link the
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
// Copyright 2022 Memgraph Ltd.
|
// Copyright 2023 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
|
||||||
@@ -116,12 +116,12 @@ Log::~Log() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void Log::Record(const std::string &address, const std::string &username, const std::string &query,
|
void Log::Record(const std::string &address, const std::string &username, const std::string &query,
|
||||||
const storage::PropertyValue ¶ms) {
|
const storage::PropertyValue ¶ms, const std::string &db) {
|
||||||
if (!started_.load(std::memory_order_relaxed)) return;
|
if (!started_.load(std::memory_order_relaxed)) return;
|
||||||
auto timestamp =
|
auto timestamp =
|
||||||
std::chrono::duration_cast<std::chrono::microseconds>(std::chrono::system_clock::now().time_since_epoch())
|
std::chrono::duration_cast<std::chrono::microseconds>(std::chrono::system_clock::now().time_since_epoch())
|
||||||
.count();
|
.count();
|
||||||
buffer_->emplace(Item{timestamp, address, username, query, params});
|
buffer_->emplace(Item{timestamp, address, username, query, params, db});
|
||||||
}
|
}
|
||||||
|
|
||||||
void Log::ReopenLog() {
|
void Log::ReopenLog() {
|
||||||
@@ -136,8 +136,8 @@ void Log::Flush() {
|
|||||||
for (uint64_t i = 0; i < buffer_size_; ++i) {
|
for (uint64_t i = 0; i < buffer_size_; ++i) {
|
||||||
auto item = buffer_->pop();
|
auto item = buffer_->pop();
|
||||||
if (!item) break;
|
if (!item) break;
|
||||||
log_.Write(fmt::format("{}.{:06d},{},{},{},{}\n", item->timestamp / 1000000, item->timestamp % 1000000,
|
log_.Write(fmt::format("{}.{:06d},{},{},{},{},{}\n", item->timestamp / 1000000, item->timestamp % 1000000,
|
||||||
item->address, item->username, utils::Escape(item->query),
|
item->address, item->username, item->db, utils::Escape(item->query),
|
||||||
utils::Escape(PropertyValueToJson(item->params).dump())));
|
utils::Escape(PropertyValueToJson(item->params).dump())));
|
||||||
}
|
}
|
||||||
log_.Sync();
|
log_.Sync();
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
// Copyright 2022 Memgraph Ltd.
|
// Copyright 2023 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
|
||||||
@@ -32,6 +32,7 @@ class Log {
|
|||||||
std::string username;
|
std::string username;
|
||||||
std::string query;
|
std::string query;
|
||||||
storage::PropertyValue params;
|
storage::PropertyValue params;
|
||||||
|
std::string db;
|
||||||
};
|
};
|
||||||
|
|
||||||
public:
|
public:
|
||||||
@@ -51,7 +52,7 @@ class Log {
|
|||||||
|
|
||||||
/// Adds an entry to the audit log. Thread-safe.
|
/// Adds an entry to the audit log. Thread-safe.
|
||||||
void Record(const std::string &address, const std::string &username, const std::string &query,
|
void Record(const std::string &address, const std::string &username, const std::string &query,
|
||||||
const storage::PropertyValue ¶ms);
|
const storage::PropertyValue ¶ms, const std::string &db);
|
||||||
|
|
||||||
/// Reopens the log file. Used for log file rotation. Thread-safe.
|
/// Reopens the log file. Used for log file rotation. Thread-safe.
|
||||||
void ReopenLog();
|
void ReopenLog();
|
||||||
|
|||||||
@@ -16,6 +16,10 @@ target_link_libraries(mg-auth mg-utils mg-kvstore mg-license )
|
|||||||
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})
|
||||||
|
|
||||||
|
find_package(OpenSSL REQUIRED)
|
||||||
|
target_link_libraries(mg-auth ${OPENSSL_LIBRARIES})
|
||||||
|
target_include_directories(mg-auth SYSTEM PUBLIC ${OPENSSL_INCLUDE_DIR})
|
||||||
|
|
||||||
# Install reference auth modules and their configuration files.
|
# Install reference auth modules and their configuration files.
|
||||||
install(PROGRAMS ${CMAKE_CURRENT_SOURCE_DIR}/reference_modules/example.py
|
install(PROGRAMS ${CMAKE_CURRENT_SOURCE_DIR}/reference_modules/example.py
|
||||||
DESTINATION lib/memgraph/auth_module)
|
DESTINATION lib/memgraph/auth_module)
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
// Copyright 2022 Memgraph Ltd.
|
// Copyright 2023 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
|
||||||
@@ -314,4 +314,57 @@ std::vector<auth::User> Auth::AllUsersForRole(const std::string &rolename_orig)
|
|||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifdef MG_ENTERPRISE
|
||||||
|
bool Auth::GrantDatabaseToUser(const std::string &db, const std::string &name) {
|
||||||
|
auto user = GetUser(name);
|
||||||
|
if (user) {
|
||||||
|
if (db == kAllDatabases) {
|
||||||
|
user->db_access().GrantAll();
|
||||||
|
} else {
|
||||||
|
user->db_access().Add(db);
|
||||||
|
}
|
||||||
|
SaveUser(*user);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool Auth::RevokeDatabaseFromUser(const std::string &db, const std::string &name) {
|
||||||
|
auto user = GetUser(name);
|
||||||
|
if (user) {
|
||||||
|
if (db == kAllDatabases) {
|
||||||
|
user->db_access().DenyAll();
|
||||||
|
} else {
|
||||||
|
user->db_access().Remove(db);
|
||||||
|
}
|
||||||
|
SaveUser(*user);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Auth::DeleteDatabase(const std::string &db) {
|
||||||
|
for (auto it = storage_.begin(kUserPrefix); it != storage_.end(kUserPrefix); ++it) {
|
||||||
|
auto username = it->first.substr(kUserPrefix.size());
|
||||||
|
auto user = GetUser(username);
|
||||||
|
if (user) {
|
||||||
|
user->db_access().Delete(db);
|
||||||
|
SaveUser(*user);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
bool Auth::SetMainDatabase(const std::string &db, const std::string &name) {
|
||||||
|
auto user = GetUser(name);
|
||||||
|
if (user) {
|
||||||
|
if (!user->db_access().SetDefault(db)) {
|
||||||
|
throw AuthException("Couldn't set default database '{}' for user '{}'!", db, name);
|
||||||
|
}
|
||||||
|
SaveUser(*user);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
} // namespace memgraph::auth
|
} // namespace memgraph::auth
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
// Copyright 2022 Memgraph Ltd.
|
// Copyright 2023 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
|
||||||
@@ -19,6 +19,9 @@
|
|||||||
#include "utils/settings.hpp"
|
#include "utils/settings.hpp"
|
||||||
|
|
||||||
namespace memgraph::auth {
|
namespace memgraph::auth {
|
||||||
|
|
||||||
|
static const constexpr char *const kAllDatabases = "*";
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 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, Permissions and FineGrainedAccessPermissions.
|
* It provides functions for managing Users, Roles, Permissions and FineGrainedAccessPermissions.
|
||||||
@@ -155,6 +158,46 @@ class Auth final {
|
|||||||
*/
|
*/
|
||||||
std::vector<User> AllUsersForRole(const std::string &rolename) const;
|
std::vector<User> AllUsersForRole(const std::string &rolename) const;
|
||||||
|
|
||||||
|
#ifdef MG_ENTERPRISE
|
||||||
|
/**
|
||||||
|
* @brief Revoke access to individual database for a user.
|
||||||
|
*
|
||||||
|
* @param db name of the database to revoke
|
||||||
|
* @param name user's username
|
||||||
|
* @return true on success
|
||||||
|
* @throw AuthException if unable to find or update the user
|
||||||
|
*/
|
||||||
|
bool RevokeDatabaseFromUser(const std::string &db, const std::string &name);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Grant access to individual database for a user.
|
||||||
|
*
|
||||||
|
* @param db name of the database to revoke
|
||||||
|
* @param name user's username
|
||||||
|
* @return true on success
|
||||||
|
* @throw AuthException if unable to find or update the user
|
||||||
|
*/
|
||||||
|
bool GrantDatabaseToUser(const std::string &db, const std::string &name);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Delete a database from all users.
|
||||||
|
*
|
||||||
|
* @param db name of the database to delete
|
||||||
|
* @throw AuthException if unable to read data
|
||||||
|
*/
|
||||||
|
void DeleteDatabase(const std::string &db);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Set main database for an individual user.
|
||||||
|
*
|
||||||
|
* @param db name of the database to revoke
|
||||||
|
* @param name user's username
|
||||||
|
* @return true on success
|
||||||
|
* @throw AuthException if unable to find or update the user
|
||||||
|
*/
|
||||||
|
bool SetMainDatabase(const std::string &db, const std::string &name);
|
||||||
|
#endif
|
||||||
|
|
||||||
private:
|
private:
|
||||||
// Even though the `kvstore::KVStore` class is guaranteed to be thread-safe,
|
// Even though the `kvstore::KVStore` class is guaranteed to be thread-safe,
|
||||||
// Auth is not thread-safe because modifying users and roles might require
|
// Auth is not thread-safe because modifying users and roles might require
|
||||||
|
|||||||
@@ -1,19 +1,64 @@
|
|||||||
// Copyright 2022 Memgraph Ltd.
|
// Copyright 2023 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
|
||||||
// this file except in compliance with the License. You may obtain a copy of the License at https://memgraph.com/legal.
|
// this file except in compliance with the License. You may obtain a copy of the License at https://memgraph.com/legal.
|
||||||
//
|
//
|
||||||
//
|
//
|
||||||
|
|
||||||
#include "auth/crypto.hpp"
|
#include "auth/crypto.hpp"
|
||||||
|
|
||||||
|
#include <iomanip>
|
||||||
|
#include <sstream>
|
||||||
|
|
||||||
|
#include <gflags/gflags.h>
|
||||||
#include <libbcrypt/bcrypt.h>
|
#include <libbcrypt/bcrypt.h>
|
||||||
|
#include <openssl/evp.h>
|
||||||
|
#include <openssl/opensslv.h>
|
||||||
|
#include <openssl/sha.h>
|
||||||
|
|
||||||
#include "auth/exceptions.hpp"
|
#include "auth/exceptions.hpp"
|
||||||
|
#include "utils/enum.hpp"
|
||||||
|
#include "utils/flag_validation.hpp"
|
||||||
|
|
||||||
|
namespace {
|
||||||
|
using namespace std::literals;
|
||||||
|
inline constexpr std::array password_encryption_mappings{
|
||||||
|
std::pair{"bcrypt"sv, memgraph::auth::PasswordEncryptionAlgorithm::BCRYPT},
|
||||||
|
std::pair{"sha256"sv, memgraph::auth::PasswordEncryptionAlgorithm::SHA256},
|
||||||
|
std::pair{"sha256-multiple"sv, memgraph::auth::PasswordEncryptionAlgorithm::SHA256_MULTIPLE}};
|
||||||
|
|
||||||
|
inline constexpr uint64_t ONE_SHA_ITERATION = 1;
|
||||||
|
inline constexpr uint64_t MULTIPLE_SHA_ITERATIONS = 1024;
|
||||||
|
} // namespace
|
||||||
|
|
||||||
|
// NOLINTNEXTLINE(cppcoreguidelines-avoid-non-const-global-variables,misc-unused-parameters)
|
||||||
|
DEFINE_VALIDATED_string(password_encryption_algorithm, "bcrypt",
|
||||||
|
"The password encryption algorithm used for authentication.", {
|
||||||
|
if (const auto result =
|
||||||
|
memgraph::utils::IsValidEnumValueString(value, password_encryption_mappings);
|
||||||
|
result.HasError()) {
|
||||||
|
const auto error = result.GetError();
|
||||||
|
switch (error) {
|
||||||
|
case memgraph::utils::ValidationError::EmptyValue: {
|
||||||
|
std::cout << "Password encryption algorithm cannot be empty." << std::endl;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case memgraph::utils::ValidationError::InvalidValue: {
|
||||||
|
std::cout << "Invalid value for password encryption algorithm. Allowed values: "
|
||||||
|
<< memgraph::utils::GetAllowedEnumValuesString(password_encryption_mappings)
|
||||||
|
<< std::endl;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
});
|
||||||
|
|
||||||
namespace memgraph::auth {
|
namespace memgraph::auth {
|
||||||
const std::string EncryptPassword(const std::string &password) {
|
namespace BCrypt {
|
||||||
|
std::string EncryptPassword(const std::string &password) {
|
||||||
char salt[BCRYPT_HASHSIZE];
|
char salt[BCRYPT_HASHSIZE];
|
||||||
char hash[BCRYPT_HASHSIZE];
|
char hash[BCRYPT_HASHSIZE];
|
||||||
|
|
||||||
@@ -28,7 +73,7 @@ const std::string EncryptPassword(const std::string &password) {
|
|||||||
throw AuthException("Couldn't hash password!");
|
throw AuthException("Couldn't hash password!");
|
||||||
}
|
}
|
||||||
|
|
||||||
return std::string(hash);
|
return {hash};
|
||||||
}
|
}
|
||||||
|
|
||||||
bool VerifyPassword(const std::string &password, const std::string &hash) {
|
bool VerifyPassword(const std::string &password, const std::string &hash) {
|
||||||
@@ -38,5 +83,102 @@ bool VerifyPassword(const std::string &password, const std::string &hash) {
|
|||||||
}
|
}
|
||||||
return ret == 0;
|
return ret == 0;
|
||||||
}
|
}
|
||||||
|
} // namespace BCrypt
|
||||||
|
|
||||||
|
namespace SHA {
|
||||||
|
#if OPENSSL_VERSION_MAJOR >= 3
|
||||||
|
std::string EncryptPasswordOpenSSL3(const std::string &password, const uint64_t number_of_iterations) {
|
||||||
|
unsigned char hash[SHA256_DIGEST_LENGTH];
|
||||||
|
|
||||||
|
EVP_MD_CTX *ctx = EVP_MD_CTX_new();
|
||||||
|
EVP_MD *md = EVP_MD_fetch(nullptr, "SHA2-256", nullptr);
|
||||||
|
|
||||||
|
EVP_DigestInit_ex(ctx, md, nullptr);
|
||||||
|
for (auto i = 0; i < number_of_iterations; i++) {
|
||||||
|
EVP_DigestUpdate(ctx, password.c_str(), password.size());
|
||||||
|
}
|
||||||
|
EVP_DigestFinal_ex(ctx, hash, nullptr);
|
||||||
|
|
||||||
|
EVP_MD_free(md);
|
||||||
|
EVP_MD_CTX_free(ctx);
|
||||||
|
|
||||||
|
std::stringstream result_stream;
|
||||||
|
for (auto hash_char : hash) {
|
||||||
|
result_stream << std::hex << std::setw(2) << std::setfill('0') << (int)hash_char;
|
||||||
|
}
|
||||||
|
|
||||||
|
return result_stream.str();
|
||||||
|
}
|
||||||
|
#else
|
||||||
|
std::string EncryptPasswordOpenSSL1_1(const std::string &password, const uint64_t number_of_iterations) {
|
||||||
|
unsigned char hash[SHA256_DIGEST_LENGTH];
|
||||||
|
|
||||||
|
SHA256_CTX sha256;
|
||||||
|
SHA256_Init(&sha256);
|
||||||
|
for (auto i = 0; i < number_of_iterations; i++) {
|
||||||
|
SHA256_Update(&sha256, password.c_str(), password.size());
|
||||||
|
}
|
||||||
|
SHA256_Final(hash, &sha256);
|
||||||
|
|
||||||
|
std::stringstream ss;
|
||||||
|
for (auto hash_char : hash) {
|
||||||
|
ss << std::hex << std::setw(2) << std::setfill('0') << (int)hash_char;
|
||||||
|
}
|
||||||
|
|
||||||
|
return ss.str();
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
std::string EncryptPassword(const std::string &password, const uint64_t number_of_iterations) {
|
||||||
|
#if OPENSSL_VERSION_MAJOR >= 3
|
||||||
|
return EncryptPasswordOpenSSL3(password, number_of_iterations);
|
||||||
|
#else
|
||||||
|
return EncryptPasswordOpenSSL1_1(password, number_of_iterations);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
bool VerifyPassword(const std::string &password, const std::string &hash, const uint64_t number_of_iterations) {
|
||||||
|
auto password_hash = EncryptPassword(password, number_of_iterations);
|
||||||
|
return password_hash == hash;
|
||||||
|
}
|
||||||
|
} // namespace SHA
|
||||||
|
|
||||||
|
bool VerifyPassword(const std::string &password, const std::string &hash) {
|
||||||
|
const auto password_encryption_algorithm = utils::StringToEnum<PasswordEncryptionAlgorithm>(
|
||||||
|
FLAGS_password_encryption_algorithm, password_encryption_mappings);
|
||||||
|
|
||||||
|
if (!password_encryption_algorithm.has_value()) {
|
||||||
|
throw AuthException("Invalid password encryption flag '{}'!", FLAGS_password_encryption_algorithm);
|
||||||
|
}
|
||||||
|
|
||||||
|
switch (password_encryption_algorithm.value()) {
|
||||||
|
case PasswordEncryptionAlgorithm::BCRYPT:
|
||||||
|
return BCrypt::VerifyPassword(password, hash);
|
||||||
|
case PasswordEncryptionAlgorithm::SHA256:
|
||||||
|
return SHA::VerifyPassword(password, hash, ONE_SHA_ITERATION);
|
||||||
|
case PasswordEncryptionAlgorithm::SHA256_MULTIPLE:
|
||||||
|
return SHA::VerifyPassword(password, hash, MULTIPLE_SHA_ITERATIONS);
|
||||||
|
}
|
||||||
|
|
||||||
|
throw AuthException("Invalid password encryption flag '{}'!", FLAGS_password_encryption_algorithm);
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string EncryptPassword(const std::string &password) {
|
||||||
|
const auto password_encryption_algorithm = utils::StringToEnum<PasswordEncryptionAlgorithm>(
|
||||||
|
FLAGS_password_encryption_algorithm, password_encryption_mappings);
|
||||||
|
|
||||||
|
if (!password_encryption_algorithm.has_value()) {
|
||||||
|
throw AuthException("Invalid password encryption flag '{}'!", FLAGS_password_encryption_algorithm);
|
||||||
|
}
|
||||||
|
|
||||||
|
switch (password_encryption_algorithm.value()) {
|
||||||
|
case PasswordEncryptionAlgorithm::BCRYPT:
|
||||||
|
return BCrypt::EncryptPassword(password);
|
||||||
|
case PasswordEncryptionAlgorithm::SHA256:
|
||||||
|
return SHA::EncryptPassword(password, ONE_SHA_ITERATION);
|
||||||
|
case PasswordEncryptionAlgorithm::SHA256_MULTIPLE:
|
||||||
|
return SHA::EncryptPassword(password, MULTIPLE_SHA_ITERATIONS);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
} // namespace memgraph::auth
|
} // namespace memgraph::auth
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
// Copyright 2022 Memgraph Ltd.
|
// Copyright 2023 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
|
||||||
@@ -11,10 +11,11 @@
|
|||||||
#include <string>
|
#include <string>
|
||||||
|
|
||||||
namespace memgraph::auth {
|
namespace memgraph::auth {
|
||||||
|
enum class PasswordEncryptionAlgorithm : uint8_t { BCRYPT, SHA256, SHA256_MULTIPLE };
|
||||||
|
|
||||||
/// @throw AuthException if unable to encrypt the password.
|
/// @throw AuthException if unable to encrypt the password.
|
||||||
const std::string EncryptPassword(const std::string &password);
|
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 memgraph::auth
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
// Copyright 2022 Memgraph Ltd.
|
// Copyright 2023 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
|
||||||
@@ -15,7 +15,10 @@
|
|||||||
|
|
||||||
#include "auth/crypto.hpp"
|
#include "auth/crypto.hpp"
|
||||||
#include "auth/exceptions.hpp"
|
#include "auth/exceptions.hpp"
|
||||||
|
#include "dbms/constants.hpp"
|
||||||
#include "license/license.hpp"
|
#include "license/license.hpp"
|
||||||
|
#include "query/constants.hpp"
|
||||||
|
#include "spdlog/spdlog.h"
|
||||||
#include "utils/cast.hpp"
|
#include "utils/cast.hpp"
|
||||||
#include "utils/logging.hpp"
|
#include "utils/logging.hpp"
|
||||||
#include "utils/settings.hpp"
|
#include "utils/settings.hpp"
|
||||||
@@ -34,13 +37,33 @@ namespace memgraph::auth {
|
|||||||
namespace {
|
namespace {
|
||||||
|
|
||||||
// Constant list of all available permissions.
|
// Constant list of all available permissions.
|
||||||
const std::vector<Permission> kPermissionsAll = {
|
const std::vector<Permission> kPermissionsAll = {Permission::MATCH,
|
||||||
Permission::MATCH, Permission::CREATE, Permission::MERGE, Permission::DELETE,
|
Permission::CREATE,
|
||||||
Permission::SET, Permission::REMOVE, Permission::INDEX, Permission::STATS,
|
Permission::MERGE,
|
||||||
Permission::CONSTRAINT, Permission::DUMP, Permission::AUTH, Permission::REPLICATION,
|
Permission::DELETE,
|
||||||
Permission::DURABILITY, Permission::READ_FILE, Permission::FREE_MEMORY, Permission::TRIGGER,
|
Permission::SET,
|
||||||
Permission::CONFIG, Permission::STREAM, Permission::MODULE_READ, Permission::MODULE_WRITE,
|
Permission::REMOVE,
|
||||||
Permission::WEBSOCKET};
|
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,
|
||||||
|
Permission::TRANSACTION_MANAGEMENT,
|
||||||
|
Permission::STORAGE_MODE,
|
||||||
|
Permission::MULTI_DATABASE_EDIT,
|
||||||
|
Permission::MULTI_DATABASE_USE,
|
||||||
|
Permission::COMPACT_MEMORY};
|
||||||
|
|
||||||
} // namespace
|
} // namespace
|
||||||
|
|
||||||
std::string PermissionToString(Permission permission) {
|
std::string PermissionToString(Permission permission) {
|
||||||
@@ -87,6 +110,16 @@ std::string PermissionToString(Permission permission) {
|
|||||||
return "MODULE_WRITE";
|
return "MODULE_WRITE";
|
||||||
case Permission::WEBSOCKET:
|
case Permission::WEBSOCKET:
|
||||||
return "WEBSOCKET";
|
return "WEBSOCKET";
|
||||||
|
case Permission::TRANSACTION_MANAGEMENT:
|
||||||
|
return "TRANSACTION_MANAGEMENT";
|
||||||
|
case Permission::STORAGE_MODE:
|
||||||
|
return "STORAGE_MODE";
|
||||||
|
case Permission::MULTI_DATABASE_EDIT:
|
||||||
|
return "MULTI_DATABASE_EDIT";
|
||||||
|
case Permission::MULTI_DATABASE_USE:
|
||||||
|
return "MULTI_DATABASE_USE";
|
||||||
|
case Permission::COMPACT_MEMORY:
|
||||||
|
return "COMPACT_MEMORY";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -264,7 +297,7 @@ PermissionLevel FineGrainedAccessPermissions::Has(const std::string &permission,
|
|||||||
|
|
||||||
void FineGrainedAccessPermissions::Grant(const std::string &permission,
|
void FineGrainedAccessPermissions::Grant(const std::string &permission,
|
||||||
const FineGrainedPermission fine_grained_permission) {
|
const FineGrainedPermission fine_grained_permission) {
|
||||||
if (permission == kAsterisk) {
|
if (permission == query::kAsterisk) {
|
||||||
global_permission_ = CalculateGrant(fine_grained_permission);
|
global_permission_ = CalculateGrant(fine_grained_permission);
|
||||||
} else {
|
} else {
|
||||||
permissions_[permission] = CalculateGrant(fine_grained_permission);
|
permissions_[permission] = CalculateGrant(fine_grained_permission);
|
||||||
@@ -272,7 +305,7 @@ void FineGrainedAccessPermissions::Grant(const std::string &permission,
|
|||||||
}
|
}
|
||||||
|
|
||||||
void FineGrainedAccessPermissions::Revoke(const std::string &permission) {
|
void FineGrainedAccessPermissions::Revoke(const std::string &permission) {
|
||||||
if (permission == kAsterisk) {
|
if (permission == query::kAsterisk) {
|
||||||
permissions_.clear();
|
permissions_.clear();
|
||||||
global_permission_ = std::nullopt;
|
global_permission_ = std::nullopt;
|
||||||
} else {
|
} else {
|
||||||
@@ -433,10 +466,11 @@ Role Role::Deserialize(const nlohmann::json &data) {
|
|||||||
auto permissions = Permissions::Deserialize(data["permissions"]);
|
auto permissions = Permissions::Deserialize(data["permissions"]);
|
||||||
#ifdef MG_ENTERPRISE
|
#ifdef MG_ENTERPRISE
|
||||||
if (memgraph::license::global_license_checker.IsEnterpriseValidFast()) {
|
if (memgraph::license::global_license_checker.IsEnterpriseValidFast()) {
|
||||||
if (!data["fine_grained_access_handler"].is_object()) {
|
FineGrainedAccessHandler fine_grained_access_handler;
|
||||||
throw AuthException("Couldn't load user data!");
|
// We can have an empty fine_grained if the user was created without a valid license
|
||||||
|
if (data["fine_grained_access_handler"].is_object()) {
|
||||||
|
fine_grained_access_handler = FineGrainedAccessHandler::Deserialize(data["fine_grained_access_handler"]);
|
||||||
}
|
}
|
||||||
auto fine_grained_access_handler = FineGrainedAccessHandler::Deserialize(data["fine_grained_access_handler"]);
|
|
||||||
return {data["rolename"], permissions, std::move(fine_grained_access_handler)};
|
return {data["rolename"], permissions, std::move(fine_grained_access_handler)};
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
@@ -453,6 +487,82 @@ bool operator==(const Role &first, const Role &second) {
|
|||||||
return first.rolename_ == second.rolename_ && first.permissions_ == second.permissions_;
|
return first.rolename_ == second.rolename_ && first.permissions_ == second.permissions_;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifdef MG_ENTERPRISE
|
||||||
|
void Databases::Add(const std::string &db) {
|
||||||
|
if (allow_all_) {
|
||||||
|
grants_dbs_.clear();
|
||||||
|
allow_all_ = false;
|
||||||
|
}
|
||||||
|
grants_dbs_.emplace(db);
|
||||||
|
denies_dbs_.erase(db);
|
||||||
|
}
|
||||||
|
|
||||||
|
void Databases::Remove(const std::string &db) {
|
||||||
|
denies_dbs_.emplace(db);
|
||||||
|
grants_dbs_.erase(db);
|
||||||
|
}
|
||||||
|
|
||||||
|
void Databases::Delete(const std::string &db) {
|
||||||
|
denies_dbs_.erase(db);
|
||||||
|
if (!allow_all_) {
|
||||||
|
grants_dbs_.erase(db);
|
||||||
|
}
|
||||||
|
// Reset if default deleted
|
||||||
|
if (default_db_ == db) {
|
||||||
|
default_db_ = "";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void Databases::GrantAll() {
|
||||||
|
allow_all_ = true;
|
||||||
|
grants_dbs_.clear();
|
||||||
|
denies_dbs_.clear();
|
||||||
|
}
|
||||||
|
|
||||||
|
void Databases::DenyAll() {
|
||||||
|
allow_all_ = false;
|
||||||
|
grants_dbs_.clear();
|
||||||
|
denies_dbs_.clear();
|
||||||
|
}
|
||||||
|
|
||||||
|
bool Databases::SetDefault(const std::string &db) {
|
||||||
|
if (!Contains(db)) return false;
|
||||||
|
default_db_ = db;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
[[nodiscard]] bool Databases::Contains(const std::string &db) const {
|
||||||
|
return !denies_dbs_.contains(db) && (allow_all_ || grants_dbs_.contains(db));
|
||||||
|
}
|
||||||
|
|
||||||
|
const std::string &Databases::GetDefault() const {
|
||||||
|
if (!Contains(default_db_)) {
|
||||||
|
throw AuthException("No access to the set default database \"{}\".", default_db_);
|
||||||
|
}
|
||||||
|
return default_db_;
|
||||||
|
}
|
||||||
|
|
||||||
|
nlohmann::json Databases::Serialize() const {
|
||||||
|
nlohmann::json data = nlohmann::json::object();
|
||||||
|
data["grants"] = grants_dbs_;
|
||||||
|
data["denies"] = denies_dbs_;
|
||||||
|
data["allow_all"] = allow_all_;
|
||||||
|
data["default"] = default_db_;
|
||||||
|
return data;
|
||||||
|
}
|
||||||
|
|
||||||
|
Databases Databases::Deserialize(const nlohmann::json &data) {
|
||||||
|
if (!data.is_object()) {
|
||||||
|
throw AuthException("Couldn't load database data!");
|
||||||
|
}
|
||||||
|
if (!data["grants"].is_structured() || !data["denies"].is_structured() || !data["allow_all"].is_boolean() ||
|
||||||
|
!data["default"].is_string()) {
|
||||||
|
throw AuthException("Couldn't load database data!");
|
||||||
|
}
|
||||||
|
return {data["allow_all"], data["grants"], data["denies"], data["default"]};
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
User::User() {}
|
User::User() {}
|
||||||
|
|
||||||
User::User(const std::string &username) : username_(utils::ToLowerCase(username)) {}
|
User::User(const std::string &username) : username_(utils::ToLowerCase(username)) {}
|
||||||
@@ -461,11 +571,12 @@ User::User(const std::string &username, const std::string &password_hash, const
|
|||||||
|
|
||||||
#ifdef MG_ENTERPRISE
|
#ifdef MG_ENTERPRISE
|
||||||
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,
|
||||||
FineGrainedAccessHandler fine_grained_access_handler)
|
FineGrainedAccessHandler fine_grained_access_handler, Databases db_access)
|
||||||
: username_(utils::ToLowerCase(username)),
|
: username_(utils::ToLowerCase(username)),
|
||||||
password_hash_(password_hash),
|
password_hash_(password_hash),
|
||||||
permissions_(permissions),
|
permissions_(permissions),
|
||||||
fine_grained_access_handler_(std::move(fine_grained_access_handler)) {}
|
fine_grained_access_handler_(std::move(fine_grained_access_handler)),
|
||||||
|
database_access_(db_access) {}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
bool User::CheckPassword(const std::string &password) {
|
bool User::CheckPassword(const std::string &password) {
|
||||||
@@ -565,8 +676,10 @@ nlohmann::json User::Serialize() const {
|
|||||||
#ifdef MG_ENTERPRISE
|
#ifdef MG_ENTERPRISE
|
||||||
if (memgraph::license::global_license_checker.IsEnterpriseValidFast()) {
|
if (memgraph::license::global_license_checker.IsEnterpriseValidFast()) {
|
||||||
data["fine_grained_access_handler"] = fine_grained_access_handler_.Serialize();
|
data["fine_grained_access_handler"] = fine_grained_access_handler_.Serialize();
|
||||||
|
data["databases"] = database_access_.Serialize();
|
||||||
} else {
|
} else {
|
||||||
data["fine_grained_access_handler"] = {};
|
data["fine_grained_access_handler"] = {};
|
||||||
|
data["databases"] = {};
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
// 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.
|
||||||
@@ -583,11 +696,21 @@ User User::Deserialize(const nlohmann::json &data) {
|
|||||||
auto permissions = Permissions::Deserialize(data["permissions"]);
|
auto permissions = Permissions::Deserialize(data["permissions"]);
|
||||||
#ifdef MG_ENTERPRISE
|
#ifdef MG_ENTERPRISE
|
||||||
if (memgraph::license::global_license_checker.IsEnterpriseValidFast()) {
|
if (memgraph::license::global_license_checker.IsEnterpriseValidFast()) {
|
||||||
if (!data["fine_grained_access_handler"].is_object()) {
|
Databases db_access;
|
||||||
throw AuthException("Couldn't load user data!");
|
if (data["databases"].is_structured()) {
|
||||||
|
db_access = Databases::Deserialize(data["databases"]);
|
||||||
|
} else {
|
||||||
|
// Back-compatibility
|
||||||
|
spdlog::warn("User without specified database access. Given access to the default database.");
|
||||||
|
db_access.Add(dbms::kDefaultDB);
|
||||||
|
db_access.SetDefault(dbms::kDefaultDB);
|
||||||
}
|
}
|
||||||
auto fine_grained_access_handler = FineGrainedAccessHandler::Deserialize(data["fine_grained_access_handler"]);
|
FineGrainedAccessHandler fine_grained_access_handler;
|
||||||
return {data["username"], data["password_hash"], permissions, fine_grained_access_handler};
|
// We can have an empty fine_grained if the user was created without a valid license
|
||||||
|
if (data["fine_grained_access_handler"].is_object()) {
|
||||||
|
fine_grained_access_handler = FineGrainedAccessHandler::Deserialize(data["fine_grained_access_handler"]);
|
||||||
|
}
|
||||||
|
return {data["username"], data["password_hash"], permissions, std::move(fine_grained_access_handler), db_access};
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
return {data["username"], data["password_hash"], permissions};
|
return {data["username"], data["password_hash"], permissions};
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
// Copyright 2022 Memgraph Ltd.
|
// Copyright 2023 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
|
||||||
@@ -9,13 +9,15 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include <optional>
|
#include <optional>
|
||||||
|
#include <set>
|
||||||
#include <string>
|
#include <string>
|
||||||
#include <unordered_map>
|
#include <unordered_map>
|
||||||
|
|
||||||
#include <json/json.hpp>
|
#include <json/json.hpp>
|
||||||
|
#include "dbms/constants.hpp"
|
||||||
|
#include "utils/logging.hpp"
|
||||||
|
|
||||||
namespace memgraph::auth {
|
namespace memgraph::auth {
|
||||||
const std::string kAsterisk = "*";
|
|
||||||
// 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
|
||||||
@@ -40,7 +42,12 @@ enum class Permission : uint64_t {
|
|||||||
STREAM = 1U << 17U,
|
STREAM = 1U << 17U,
|
||||||
MODULE_READ = 1U << 18U,
|
MODULE_READ = 1U << 18U,
|
||||||
MODULE_WRITE = 1U << 19U,
|
MODULE_WRITE = 1U << 19U,
|
||||||
WEBSOCKET = 1U << 20U
|
WEBSOCKET = 1U << 20U,
|
||||||
|
TRANSACTION_MANAGEMENT = 1U << 21U,
|
||||||
|
STORAGE_MODE = 1U << 22U,
|
||||||
|
MULTI_DATABASE_EDIT = 1U << 23U,
|
||||||
|
MULTI_DATABASE_USE = 1U << 24U,
|
||||||
|
COMPACT_MEMORY = 1U << 25U,
|
||||||
};
|
};
|
||||||
// clang-format on
|
// clang-format on
|
||||||
|
|
||||||
@@ -236,6 +243,85 @@ class Role final {
|
|||||||
|
|
||||||
bool operator==(const Role &first, const Role &second);
|
bool operator==(const Role &first, const Role &second);
|
||||||
|
|
||||||
|
#ifdef MG_ENTERPRISE
|
||||||
|
class Databases final {
|
||||||
|
public:
|
||||||
|
Databases() : grants_dbs_({dbms::kDefaultDB}), allow_all_(false), default_db_(dbms::kDefaultDB) {}
|
||||||
|
|
||||||
|
Databases(const Databases &) = default;
|
||||||
|
Databases &operator=(const Databases &) = default;
|
||||||
|
Databases(Databases &&) noexcept = default;
|
||||||
|
Databases &operator=(Databases &&) noexcept = default;
|
||||||
|
~Databases() = default;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Add database to the list of granted access. @note allow_all_ will be false after execution
|
||||||
|
*
|
||||||
|
* @param db name of the database to grant access to
|
||||||
|
*/
|
||||||
|
void Add(const std::string &db);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Remove database to the list of granted access.
|
||||||
|
* @note if allow_all_ is set, the flag will remain set and the
|
||||||
|
* database will be added to the set of denied databases.
|
||||||
|
*
|
||||||
|
* @param db name of the database to grant access to
|
||||||
|
*/
|
||||||
|
void Remove(const std::string &db);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Called when database is dropped. Removes it from granted (if allow_all is false) and denied set.
|
||||||
|
* @note allow_all_ is not changed
|
||||||
|
*
|
||||||
|
* @param db name of the database to grant access to
|
||||||
|
*/
|
||||||
|
void Delete(const std::string &db);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Set allow_all_ to true and clears grants and denied sets.
|
||||||
|
*/
|
||||||
|
void GrantAll();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Set allow_all_ to false and clears grants and denied sets.
|
||||||
|
*/
|
||||||
|
void DenyAll();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Set the default database.
|
||||||
|
*/
|
||||||
|
bool SetDefault(const std::string &db);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Checks if access is grated to the database.
|
||||||
|
*
|
||||||
|
* @param db name of the database
|
||||||
|
* @return true if allow_all and not denied or granted
|
||||||
|
*/
|
||||||
|
bool Contains(const std::string &db) const;
|
||||||
|
|
||||||
|
bool GetAllowAll() const { return allow_all_; }
|
||||||
|
const std::set<std::string> &GetGrants() const { return grants_dbs_; }
|
||||||
|
const std::set<std::string> &GetDenies() const { return denies_dbs_; }
|
||||||
|
const std::string &GetDefault() const;
|
||||||
|
|
||||||
|
nlohmann::json Serialize() const;
|
||||||
|
/// @throw AuthException if unable to deserialize.
|
||||||
|
static Databases Deserialize(const nlohmann::json &data);
|
||||||
|
|
||||||
|
private:
|
||||||
|
Databases(bool allow_all, std::set<std::string> grant, std::set<std::string> deny,
|
||||||
|
const std::string &default_db = dbms::kDefaultDB)
|
||||||
|
: grants_dbs_(grant), denies_dbs_(deny), allow_all_(allow_all), default_db_(default_db) {}
|
||||||
|
|
||||||
|
std::set<std::string> grants_dbs_; //!< set of databases with granted access
|
||||||
|
std::set<std::string> denies_dbs_; //!< set of databases with denied access
|
||||||
|
bool allow_all_; //!< flag to allow access to everything (denied overrides this)
|
||||||
|
std::string default_db_; //!< user's default database
|
||||||
|
};
|
||||||
|
#endif
|
||||||
|
|
||||||
// TODO (mferencevic): Implement password expiry.
|
// TODO (mferencevic): Implement password expiry.
|
||||||
class User final {
|
class User final {
|
||||||
public:
|
public:
|
||||||
@@ -245,7 +331,7 @@ 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);
|
||||||
#ifdef MG_ENTERPRISE
|
#ifdef MG_ENTERPRISE
|
||||||
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,
|
||||||
FineGrainedAccessHandler fine_grained_access_handler);
|
FineGrainedAccessHandler fine_grained_access_handler, Databases db_access = {});
|
||||||
#endif
|
#endif
|
||||||
User(const User &) = default;
|
User(const User &) = default;
|
||||||
User &operator=(const User &) = default;
|
User &operator=(const User &) = default;
|
||||||
@@ -278,6 +364,11 @@ class User final {
|
|||||||
|
|
||||||
const Role *role() const;
|
const Role *role() const;
|
||||||
|
|
||||||
|
#ifdef MG_ENTERPRISE
|
||||||
|
Databases &db_access() { return database_access_; }
|
||||||
|
const Databases &db_access() const { return database_access_; }
|
||||||
|
#endif
|
||||||
|
|
||||||
nlohmann::json Serialize() const;
|
nlohmann::json Serialize() const;
|
||||||
|
|
||||||
/// @throw AuthException if unable to deserialize.
|
/// @throw AuthException if unable to deserialize.
|
||||||
@@ -291,6 +382,7 @@ class User final {
|
|||||||
Permissions permissions_;
|
Permissions permissions_;
|
||||||
#ifdef MG_ENTERPRISE
|
#ifdef MG_ENTERPRISE
|
||||||
FineGrainedAccessHandler fine_grained_access_handler_;
|
FineGrainedAccessHandler fine_grained_access_handler_;
|
||||||
|
Databases database_access_;
|
||||||
#endif
|
#endif
|
||||||
std::optional<Role> role_;
|
std::optional<Role> role_;
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -22,3 +22,4 @@ target_link_libraries(mg-communication Boost::headers Threads::Threads mg-utils
|
|||||||
find_package(OpenSSL REQUIRED)
|
find_package(OpenSSL REQUIRED)
|
||||||
target_link_libraries(mg-communication ${OPENSSL_LIBRARIES})
|
target_link_libraries(mg-communication ${OPENSSL_LIBRARIES})
|
||||||
target_include_directories(mg-communication SYSTEM PUBLIC ${OPENSSL_INCLUDE_DIR})
|
target_include_directories(mg-communication SYSTEM PUBLIC ${OPENSSL_INCLUDE_DIR})
|
||||||
|
target_precompile_headers(mg-communication INTERFACE http/server.hpp <boost/beast/websocket.hpp> bolt/v1/session.hpp)
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
// Copyright 2022 Memgraph Ltd.
|
// Copyright 2023 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
|
||||||
@@ -19,7 +19,9 @@ inline constexpr uint8_t kPreamble[4] = {0x60, 0x60, 0xB0, 0x17};
|
|||||||
|
|
||||||
enum class Signature : uint8_t {
|
enum class Signature : uint8_t {
|
||||||
Noop = 0x00,
|
Noop = 0x00,
|
||||||
Init = 0x01,
|
Init = 0x01, // v3+ now HELLO
|
||||||
|
LogOn = 0x6A,
|
||||||
|
LogOff = 0x6B,
|
||||||
AckFailure = 0x0E, // only v1
|
AckFailure = 0x0E, // only v1
|
||||||
Reset = 0x0F,
|
Reset = 0x0F,
|
||||||
Goodbye = 0x02,
|
Goodbye = 0x02,
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
// Copyright 2022 Memgraph Ltd.
|
// Copyright 2023 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 @@ inline constexpr size_t kChunkWholeSize = kChunkHeaderSize + kChunkMaxDataSize;
|
|||||||
*/
|
*/
|
||||||
inline constexpr size_t kHandshakeSize = 20;
|
inline constexpr size_t kHandshakeSize = 20;
|
||||||
|
|
||||||
inline constexpr uint16_t kSupportedVersions[] = {0x0100, 0x0400, 0x0401, 0x0403};
|
inline constexpr uint16_t kSupportedVersions[] = {0x0100, 0x0400, 0x0401, 0x0403, 0x0502};
|
||||||
|
|
||||||
inline constexpr int kPullAll = -1;
|
inline constexpr int kPullAll = -1;
|
||||||
inline constexpr int kPullLast = -1;
|
inline constexpr int kPullLast = -1;
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
// Copyright 2022 Memgraph Ltd.
|
// Copyright 2023 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
|
||||||
@@ -33,7 +33,14 @@ namespace memgraph::communication::bolt {
|
|||||||
template <typename Buffer>
|
template <typename Buffer>
|
||||||
class Decoder {
|
class Decoder {
|
||||||
public:
|
public:
|
||||||
explicit Decoder(Buffer &buffer) : buffer_(buffer) {}
|
explicit Decoder(Buffer &buffer) : buffer_(buffer), major_v_(0) {}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Lets the user update the version.
|
||||||
|
* This is all single thread for now. TODO: Update if ever multithreaded.
|
||||||
|
* @param major_v the major version of the Bolt protocol used.
|
||||||
|
*/
|
||||||
|
void UpdateVersion(int major_v) { major_v_ = major_v; }
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Reads a Value from the available data in the buffer.
|
* Reads a Value from the available data in the buffer.
|
||||||
@@ -208,6 +215,10 @@ class Decoder {
|
|||||||
|
|
||||||
protected:
|
protected:
|
||||||
Buffer &buffer_;
|
Buffer &buffer_;
|
||||||
|
int major_v_; //!< Major version of the underlying Bolt protocol
|
||||||
|
// TODO: when refactoring
|
||||||
|
// Ideally the major_v would be a compile time constant. If the higher level (Bolt driver) ends up being separate
|
||||||
|
// classes, this could be just a template and each version of the driver would use the appropriate decoder.
|
||||||
|
|
||||||
private:
|
private:
|
||||||
bool ReadNull(const Marker &marker, Value *data) {
|
bool ReadNull(const Marker &marker, Value *data) {
|
||||||
@@ -370,11 +381,7 @@ class Decoder {
|
|||||||
}
|
}
|
||||||
ret.emplace(std::move(dv_key.ValueString()), std::move(dv_val));
|
ret.emplace(std::move(dv_key.ValueString()), std::move(dv_val));
|
||||||
}
|
}
|
||||||
if (ret.size() != size) {
|
return ret.size() == size;
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool ReadVertex(Value *data) {
|
bool ReadVertex(Value *data) {
|
||||||
@@ -407,6 +414,14 @@ class Decoder {
|
|||||||
}
|
}
|
||||||
vertex.properties = std::move(dv.ValueMap());
|
vertex.properties = std::move(dv.ValueMap());
|
||||||
|
|
||||||
|
if (major_v_ > 4) {
|
||||||
|
// element_id introduced in v5.0
|
||||||
|
if (!ReadValue(&dv, Value::Type::String)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
vertex.element_id = std::move(dv.ValueString());
|
||||||
|
}
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -445,6 +460,23 @@ class Decoder {
|
|||||||
}
|
}
|
||||||
edge.properties = std::move(dv.ValueMap());
|
edge.properties = std::move(dv.ValueMap());
|
||||||
|
|
||||||
|
if (major_v_ > 4) {
|
||||||
|
// element_id introduced in v5.0
|
||||||
|
if (!ReadValue(&dv, Value::Type::String)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
edge.element_id = std::move(dv.ValueString());
|
||||||
|
// from_element_id introduced in v5.0
|
||||||
|
if (!ReadValue(&dv, Value::Type::String)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
edge.from_element_id = std::move(dv.ValueString());
|
||||||
|
// to_element_id introduced in v5.0
|
||||||
|
if (!ReadValue(&dv, Value::Type::String)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
edge.to_element_id = std::move(dv.ValueString());
|
||||||
|
}
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -471,6 +503,14 @@ class Decoder {
|
|||||||
}
|
}
|
||||||
edge.properties = std::move(dv.ValueMap());
|
edge.properties = std::move(dv.ValueMap());
|
||||||
|
|
||||||
|
if (major_v_ > 4) {
|
||||||
|
// element_id introduced in v5.0
|
||||||
|
if (!ReadValue(&dv, Value::Type::String)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
edge.element_id = std::move(dv.ValueString());
|
||||||
|
}
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
// Copyright 2022 Memgraph Ltd.
|
// Copyright 2023 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
|
||||||
@@ -36,7 +36,14 @@ namespace memgraph::communication::bolt {
|
|||||||
template <typename Buffer>
|
template <typename Buffer>
|
||||||
class BaseEncoder {
|
class BaseEncoder {
|
||||||
public:
|
public:
|
||||||
explicit BaseEncoder(Buffer &buffer) : buffer_(buffer) {}
|
explicit BaseEncoder(Buffer &buffer) : buffer_(buffer), major_v_(0) {}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Lets the user update the version.
|
||||||
|
* This is all single thread for now. TODO: Update if ever multithreaded.
|
||||||
|
* @param major_v the major version of the Bolt protocol used.
|
||||||
|
*/
|
||||||
|
void UpdateVersion(int major_v) { major_v_ = major_v; }
|
||||||
|
|
||||||
void WriteRAW(const uint8_t *data, uint64_t len) { buffer_.Write(data, len); }
|
void WriteRAW(const uint8_t *data, uint64_t len) { buffer_.Write(data, len); }
|
||||||
|
|
||||||
@@ -116,7 +123,8 @@ class BaseEncoder {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void WriteVertex(const Vertex &vertex) {
|
void WriteVertex(const Vertex &vertex) {
|
||||||
WriteRAW(utils::UnderlyingCast(Marker::TinyStruct) + 3);
|
int struct_n = 3 + 1 * int(major_v_ > 4); // element_id introduced from v5
|
||||||
|
WriteRAW(utils::UnderlyingCast(Marker::TinyStruct) + struct_n);
|
||||||
WriteRAW(utils::UnderlyingCast(Signature::Node));
|
WriteRAW(utils::UnderlyingCast(Signature::Node));
|
||||||
WriteInt(vertex.id.AsInt());
|
WriteInt(vertex.id.AsInt());
|
||||||
|
|
||||||
@@ -132,10 +140,16 @@ class BaseEncoder {
|
|||||||
WriteString(prop.first);
|
WriteString(prop.first);
|
||||||
WriteValue(prop.second);
|
WriteValue(prop.second);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (major_v_ > 4) {
|
||||||
|
// element_id introduced in v5.0
|
||||||
|
WriteString(vertex.element_id);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void WriteEdge(const Edge &edge, bool unbound = false) {
|
void WriteEdge(const Edge &edge, bool unbound = false) {
|
||||||
WriteRAW(utils::UnderlyingCast(Marker::TinyStruct) + (unbound ? 3 : 5));
|
int struct_n = (unbound ? 3 + 1 * int(major_v_ > 4) : 5 + 3 * int(major_v_ > 4)); // element_id introduced from v5
|
||||||
|
WriteRAW(utils::UnderlyingCast(Marker::TinyStruct) + struct_n);
|
||||||
WriteRAW(utils::UnderlyingCast(unbound ? Signature::UnboundRelationship : Signature::Relationship));
|
WriteRAW(utils::UnderlyingCast(unbound ? Signature::UnboundRelationship : Signature::Relationship));
|
||||||
|
|
||||||
WriteInt(edge.id.AsInt());
|
WriteInt(edge.id.AsInt());
|
||||||
@@ -152,10 +166,22 @@ class BaseEncoder {
|
|||||||
WriteString(prop.first);
|
WriteString(prop.first);
|
||||||
WriteValue(prop.second);
|
WriteValue(prop.second);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (major_v_ > 4) {
|
||||||
|
// element_id introduced in v5.0
|
||||||
|
WriteString(edge.element_id);
|
||||||
|
if (!unbound) {
|
||||||
|
// from_element_id introduced in v5.0
|
||||||
|
WriteString(edge.from_element_id);
|
||||||
|
// to_element_id introduced in v5.0
|
||||||
|
WriteString(edge.to_element_id);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void WriteEdge(const UnboundedEdge &edge) {
|
void WriteEdge(const UnboundedEdge &edge) {
|
||||||
WriteRAW(utils::UnderlyingCast(Marker::TinyStruct) + 3);
|
const int struct_n = 3 + 1 * int(major_v_ > 4); // element_id introduced from v5
|
||||||
|
WriteRAW(utils::UnderlyingCast(Marker::TinyStruct) + struct_n);
|
||||||
WriteRAW(utils::UnderlyingCast(Signature::UnboundRelationship));
|
WriteRAW(utils::UnderlyingCast(Signature::UnboundRelationship));
|
||||||
|
|
||||||
WriteInt(edge.id.AsInt());
|
WriteInt(edge.id.AsInt());
|
||||||
@@ -168,6 +194,11 @@ class BaseEncoder {
|
|||||||
WriteString(prop.first);
|
WriteString(prop.first);
|
||||||
WriteValue(prop.second);
|
WriteValue(prop.second);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (major_v_ > 4) {
|
||||||
|
// element_id introduced in v5.0
|
||||||
|
WriteString(edge.element_id);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void WritePath(const Path &path) {
|
void WritePath(const Path &path) {
|
||||||
@@ -264,6 +295,7 @@ class BaseEncoder {
|
|||||||
|
|
||||||
protected:
|
protected:
|
||||||
Buffer &buffer_;
|
Buffer &buffer_;
|
||||||
|
int major_v_; //!< Major version of the underlying Bolt protocol (TODO: Think about reimplementing the versioning)
|
||||||
|
|
||||||
private:
|
private:
|
||||||
template <class T>
|
template <class T>
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
// Copyright 2022 Memgraph Ltd.
|
// Copyright 2023 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
|
||||||
@@ -41,6 +41,8 @@ class ClientEncoder : private BaseEncoder<Buffer> {
|
|||||||
public:
|
public:
|
||||||
ClientEncoder(Buffer &buffer) : BaseEncoder<Buffer>(buffer) {}
|
ClientEncoder(Buffer &buffer) : BaseEncoder<Buffer>(buffer) {}
|
||||||
|
|
||||||
|
using BaseEncoder<Buffer>::UpdateVersion;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Writes a Init message.
|
* Writes a Init message.
|
||||||
*
|
*
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
// Copyright 2022 Memgraph Ltd.
|
// Copyright 2023 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
|
||||||
@@ -34,6 +34,8 @@ class Encoder : private BaseEncoder<Buffer> {
|
|||||||
public:
|
public:
|
||||||
Encoder(Buffer &buffer) : BaseEncoder<Buffer>(buffer) {}
|
Encoder(Buffer &buffer) : BaseEncoder<Buffer>(buffer) {}
|
||||||
|
|
||||||
|
using BaseEncoder<Buffer>::UpdateVersion;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Sends a Record message.
|
* Sends a Record message.
|
||||||
*
|
*
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
// Copyright 2022 Memgraph Ltd.
|
// Copyright 2023 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,6 +11,8 @@
|
|||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
|
#include <concepts>
|
||||||
|
#include <cstddef>
|
||||||
#include <optional>
|
#include <optional>
|
||||||
#include <thread>
|
#include <thread>
|
||||||
|
|
||||||
@@ -24,8 +26,12 @@
|
|||||||
#include "communication/bolt/v1/states/executing.hpp"
|
#include "communication/bolt/v1/states/executing.hpp"
|
||||||
#include "communication/bolt/v1/states/handshake.hpp"
|
#include "communication/bolt/v1/states/handshake.hpp"
|
||||||
#include "communication/bolt/v1/states/init.hpp"
|
#include "communication/bolt/v1/states/init.hpp"
|
||||||
|
#include "communication/bolt/v1/value.hpp"
|
||||||
|
#include "dbms/constants.hpp"
|
||||||
|
#include "dbms/global.hpp"
|
||||||
#include "utils/exceptions.hpp"
|
#include "utils/exceptions.hpp"
|
||||||
#include "utils/logging.hpp"
|
#include "utils/logging.hpp"
|
||||||
|
#include "utils/uuid.hpp"
|
||||||
|
|
||||||
namespace memgraph::communication::bolt {
|
namespace memgraph::communication::bolt {
|
||||||
|
|
||||||
@@ -48,14 +54,26 @@ class SessionException : public utils::BasicException {
|
|||||||
* @tparam TOutputStream type of output stream that will be used
|
* @tparam TOutputStream type of output stream that will be used
|
||||||
*/
|
*/
|
||||||
template <typename TInputStream, typename TOutputStream>
|
template <typename TInputStream, typename TOutputStream>
|
||||||
class Session {
|
class Session : public dbms::SessionInterface {
|
||||||
public:
|
public:
|
||||||
using TEncoder = Encoder<ChunkedEncoderBuffer<TOutputStream>>;
|
using TEncoder = Encoder<ChunkedEncoderBuffer<TOutputStream>>;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Construct a new Session object
|
||||||
|
*
|
||||||
|
* @param input_stream stream to read from
|
||||||
|
* @param output_stream stream to write to
|
||||||
|
* @param impl a default high-level implementation to use (has to be defined)
|
||||||
|
*/
|
||||||
Session(TInputStream *input_stream, TOutputStream *output_stream)
|
Session(TInputStream *input_stream, TOutputStream *output_stream)
|
||||||
: input_stream_(*input_stream), output_stream_(*output_stream) {}
|
: input_stream_(*input_stream), output_stream_(*output_stream), session_uuid_(utils::GenerateUUID()) {}
|
||||||
|
|
||||||
virtual ~Session() {}
|
virtual ~Session() = default;
|
||||||
|
|
||||||
|
Session(const Session &) = delete;
|
||||||
|
Session &operator=(const Session &) = delete;
|
||||||
|
Session(Session &&) noexcept = delete;
|
||||||
|
Session &operator=(Session &&) noexcept = delete;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Process the given `query` with `params`.
|
* Process the given `query` with `params`.
|
||||||
@@ -63,7 +81,10 @@ class Session {
|
|||||||
* if an explicit transaction was started.
|
* if an explicit transaction was started.
|
||||||
*/
|
*/
|
||||||
virtual std::pair<std::vector<std::string>, std::optional<int>> Interpret(
|
virtual std::pair<std::vector<std::string>, std::optional<int>> Interpret(
|
||||||
const std::string &query, const std::map<std::string, Value> ¶ms) = 0;
|
const std::string &query, const std::map<std::string, Value> ¶ms,
|
||||||
|
const std::map<std::string, memgraph::communication::bolt::Value> &extra) = 0;
|
||||||
|
|
||||||
|
virtual void Configure(const std::map<std::string, memgraph::communication::bolt::Value> &run_time_info) = 0;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Put results of the processed query in the `encoder`.
|
* Put results of the processed query in the `encoder`.
|
||||||
@@ -85,7 +106,7 @@ class Session {
|
|||||||
*/
|
*/
|
||||||
virtual std::map<std::string, Value> Discard(std::optional<int> n, std::optional<int> qid) = 0;
|
virtual std::map<std::string, Value> Discard(std::optional<int> n, std::optional<int> qid) = 0;
|
||||||
|
|
||||||
virtual void BeginTransaction() = 0;
|
virtual void BeginTransaction(const std::map<std::string, memgraph::communication::bolt::Value> ¶ms) = 0;
|
||||||
virtual void CommitTransaction() = 0;
|
virtual void CommitTransaction() = 0;
|
||||||
virtual void RollbackTransaction() = 0;
|
virtual void RollbackTransaction() = 0;
|
||||||
|
|
||||||
@@ -98,7 +119,6 @@ class Session {
|
|||||||
/** Return the name of the server that should be used for the Bolt INIT
|
/** Return the name of the server that should be used for the Bolt INIT
|
||||||
* message. */
|
* message. */
|
||||||
virtual std::optional<std::string> GetServerNameForInit() = 0;
|
virtual std::optional<std::string> GetServerNameForInit() = 0;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Executes the session after data has been read into the buffer.
|
* Executes the session after data has been read into the buffer.
|
||||||
* Goes through the bolt states in order to execute commands from the client.
|
* Goes through the bolt states in order to execute commands from the client.
|
||||||
@@ -120,6 +140,9 @@ class Session {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
handshake_done_ = true;
|
handshake_done_ = true;
|
||||||
|
// Update the decoder's Bolt version (v5 has changed the undelying structure)
|
||||||
|
decoder_.UpdateVersion(version_.major);
|
||||||
|
encoder_.UpdateVersion(version_.major);
|
||||||
}
|
}
|
||||||
|
|
||||||
ChunkState chunk_state;
|
ChunkState chunk_state;
|
||||||
@@ -157,8 +180,7 @@ class Session {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: Rethink if there is a way to hide some members. At the momement all
|
// TODO: Rethink if there is a way to hide some members. At the momement all of them are public.
|
||||||
// of them are public.
|
|
||||||
TInputStream &input_stream_;
|
TInputStream &input_stream_;
|
||||||
TOutputStream &output_stream_;
|
TOutputStream &output_stream_;
|
||||||
|
|
||||||
@@ -178,6 +200,9 @@ class Session {
|
|||||||
|
|
||||||
Version version_;
|
Version version_;
|
||||||
|
|
||||||
|
std::string GetDatabaseName() const override = 0;
|
||||||
|
std::string UUID() const final { return session_uuid_; }
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void ClientFailureInvalidData() {
|
void ClientFailureInvalidData() {
|
||||||
// Set the state to Close.
|
// Set the state to Close.
|
||||||
@@ -193,6 +218,8 @@ class Session {
|
|||||||
// of the session to trigger session cleanup and socket close.
|
// of the session to trigger session cleanup and socket close.
|
||||||
throw SessionException("Something went wrong during session execution!");
|
throw SessionException("Something went wrong during session execution!");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const std::string session_uuid_; //!< unique identifier of the session (auto generated)
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace memgraph::communication::bolt
|
} // namespace memgraph::communication::bolt
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
// Copyright 2022 Memgraph Ltd.
|
// Copyright 2023 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,10 +22,15 @@
|
|||||||
#include "communication/bolt/v1/state.hpp"
|
#include "communication/bolt/v1/state.hpp"
|
||||||
#include "communication/bolt/v1/states/handlers.hpp"
|
#include "communication/bolt/v1/states/handlers.hpp"
|
||||||
#include "communication/bolt/v1/value.hpp"
|
#include "communication/bolt/v1/value.hpp"
|
||||||
|
#include "utils/event_counter.hpp"
|
||||||
#include "utils/likely.hpp"
|
#include "utils/likely.hpp"
|
||||||
#include "utils/logging.hpp"
|
#include "utils/logging.hpp"
|
||||||
#include "utils/message.hpp"
|
#include "utils/message.hpp"
|
||||||
|
|
||||||
|
namespace memgraph::metrics {
|
||||||
|
extern const Event BoltMessages;
|
||||||
|
} // namespace memgraph::metrics
|
||||||
|
|
||||||
namespace memgraph::communication::bolt {
|
namespace memgraph::communication::bolt {
|
||||||
|
|
||||||
template <typename TSession>
|
template <typename TSession>
|
||||||
@@ -86,6 +91,37 @@ State RunHandlerV4(Signature signature, TSession &session, State state, Marker m
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
template <typename TSession>
|
||||||
|
State RunHandlerV5(Signature signature, TSession &session, State state, Marker marker) {
|
||||||
|
switch (signature) {
|
||||||
|
case Signature::Run:
|
||||||
|
return HandleRunV5<TSession>(session, state, marker);
|
||||||
|
case Signature::Pull:
|
||||||
|
return HandlePullV5<TSession>(session, state, marker);
|
||||||
|
case Signature::Discard:
|
||||||
|
return HandleDiscardV5<TSession>(session, state, marker);
|
||||||
|
case Signature::Reset:
|
||||||
|
return HandleReset<TSession>(session, marker);
|
||||||
|
case Signature::Begin:
|
||||||
|
return HandleBegin<TSession>(session, state, marker);
|
||||||
|
case Signature::Commit:
|
||||||
|
return HandleCommit<TSession>(session, state, marker);
|
||||||
|
case Signature::Goodbye:
|
||||||
|
return HandleGoodbye<TSession>();
|
||||||
|
case Signature::Rollback:
|
||||||
|
return HandleRollback<TSession>(session, state, marker);
|
||||||
|
case Signature::Noop:
|
||||||
|
return HandleNoop<TSession>(state);
|
||||||
|
case Signature::Route:
|
||||||
|
return HandleRoute<TSession>(session, marker);
|
||||||
|
case Signature::LogOff:
|
||||||
|
return HandleLogOff<TSession>();
|
||||||
|
default:
|
||||||
|
spdlog::trace("Unrecognized signature received (0x{:02X})!", utils::UnderlyingCast(signature));
|
||||||
|
return State::Close;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Executor state run function
|
* Executor state run function
|
||||||
* This function executes an initialized Bolt session.
|
* This function executes an initialized Bolt session.
|
||||||
@@ -103,8 +139,10 @@ State StateExecutingRun(TSession &session, State state) {
|
|||||||
|
|
||||||
switch (session.version_.major) {
|
switch (session.version_.major) {
|
||||||
case 1:
|
case 1:
|
||||||
|
memgraph::metrics::IncrementCounter(memgraph::metrics::BoltMessages);
|
||||||
return RunHandlerV1(signature, session, state, marker);
|
return RunHandlerV1(signature, session, state, marker);
|
||||||
case 4: {
|
case 4: {
|
||||||
|
memgraph::metrics::IncrementCounter(memgraph::metrics::BoltMessages);
|
||||||
if (session.version_.minor >= 3) {
|
if (session.version_.minor >= 3) {
|
||||||
return RunHandlerV4<TSession, 3>(signature, session, state, marker);
|
return RunHandlerV4<TSession, 3>(signature, session, state, marker);
|
||||||
}
|
}
|
||||||
@@ -113,6 +151,9 @@ State StateExecutingRun(TSession &session, State state) {
|
|||||||
}
|
}
|
||||||
return RunHandlerV4<TSession>(signature, session, state, marker);
|
return RunHandlerV4<TSession>(signature, session, state, marker);
|
||||||
}
|
}
|
||||||
|
case 5:
|
||||||
|
memgraph::metrics::IncrementCounter(memgraph::metrics::BoltMessages);
|
||||||
|
return RunHandlerV5<TSession>(signature, session, state, marker);
|
||||||
default:
|
default:
|
||||||
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;
|
||||||
|
|||||||
@@ -11,7 +11,9 @@
|
|||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
|
#include <exception>
|
||||||
#include <map>
|
#include <map>
|
||||||
|
#include <optional>
|
||||||
#include <string>
|
#include <string>
|
||||||
#include <string_view>
|
#include <string_view>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
@@ -22,6 +24,7 @@
|
|||||||
#include "communication/bolt/v1/state.hpp"
|
#include "communication/bolt/v1/state.hpp"
|
||||||
#include "communication/bolt/v1/value.hpp"
|
#include "communication/bolt/v1/value.hpp"
|
||||||
#include "communication/exceptions.hpp"
|
#include "communication/exceptions.hpp"
|
||||||
|
#include "storage/v2/property_value.hpp"
|
||||||
#include "utils/logging.hpp"
|
#include "utils/logging.hpp"
|
||||||
#include "utils/message.hpp"
|
#include "utils/message.hpp"
|
||||||
|
|
||||||
@@ -205,11 +208,11 @@ State HandleRunV1(TSession &session, const State state, const Marker marker) {
|
|||||||
|
|
||||||
DMG_ASSERT(!session.encoder_buffer_.HasData(), "There should be no data to write in this state");
|
DMG_ASSERT(!session.encoder_buffer_.HasData(), "There should be no data to write in this state");
|
||||||
|
|
||||||
spdlog::debug("[Run] '{}'", query.ValueString());
|
spdlog::debug("[Run - {}] '{}'", session.GetDatabaseName(), query.ValueString());
|
||||||
|
|
||||||
try {
|
try {
|
||||||
// Interpret can throw.
|
// Interpret can throw.
|
||||||
const auto [header, qid] = session.Interpret(query.ValueString(), params.ValueMap());
|
const auto [header, qid] = session.Interpret(query.ValueString(), params.ValueMap(), {});
|
||||||
// Convert std::string to Value
|
// Convert std::string to Value
|
||||||
std::vector<Value> vec;
|
std::vector<Value> vec;
|
||||||
std::map<std::string, Value> data;
|
std::map<std::string, Value> data;
|
||||||
@@ -250,6 +253,7 @@ State HandleRunV4(TSession &session, const State state, const Marker marker) {
|
|||||||
// Even though this part seems unnecessary it is needed to move the buffer
|
// Even though this part seems unnecessary it is needed to move the buffer
|
||||||
if (!session.decoder_.ReadValue(&extra, Value::Type::Map)) {
|
if (!session.decoder_.ReadValue(&extra, Value::Type::Map)) {
|
||||||
spdlog::trace("Couldn't read extra field!");
|
spdlog::trace("Couldn't read extra field!");
|
||||||
|
return State::Close;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (state != State::Idle) {
|
if (state != State::Idle) {
|
||||||
@@ -262,11 +266,17 @@ State HandleRunV4(TSession &session, const State state, const Marker marker) {
|
|||||||
|
|
||||||
DMG_ASSERT(!session.encoder_buffer_.HasData(), "There should be no data to write in this state");
|
DMG_ASSERT(!session.encoder_buffer_.HasData(), "There should be no data to write in this state");
|
||||||
|
|
||||||
spdlog::debug("[Run] '{}'", query.ValueString());
|
try {
|
||||||
|
session.Configure(extra.ValueMap());
|
||||||
|
} catch (const std::exception &e) {
|
||||||
|
return HandleFailure(session, e);
|
||||||
|
}
|
||||||
|
|
||||||
|
spdlog::debug("[Run - {}] '{}'", session.GetDatabaseName(), query.ValueString());
|
||||||
|
|
||||||
try {
|
try {
|
||||||
// Interpret can throw.
|
// Interpret can throw.
|
||||||
const auto [header, qid] = session.Interpret(query.ValueString(), params.ValueMap());
|
const auto [header, qid] = session.Interpret(query.ValueString(), params.ValueMap(), extra.ValueMap());
|
||||||
// Convert std::string to Value
|
// Convert std::string to Value
|
||||||
std::vector<Value> vec;
|
std::vector<Value> vec;
|
||||||
std::map<std::string, Value> data;
|
std::map<std::string, Value> data;
|
||||||
@@ -288,6 +298,12 @@ State HandleRunV4(TSession &session, const State state, const Marker marker) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
template <typename TSession>
|
||||||
|
State HandleRunV5(TSession &session, const State state, const Marker marker) {
|
||||||
|
// Using V4 on purpose
|
||||||
|
return HandleRunV4<TSession>(session, state, marker);
|
||||||
|
}
|
||||||
|
|
||||||
template <typename TSession>
|
template <typename TSession>
|
||||||
State HandlePullV1(TSession &session, const State state, const Marker marker) {
|
State HandlePullV1(TSession &session, const State state, const Marker marker) {
|
||||||
return details::HandlePullDiscardV1<true>(session, state, marker);
|
return details::HandlePullDiscardV1<true>(session, state, marker);
|
||||||
@@ -298,6 +314,12 @@ State HandlePullV4(TSession &session, const State state, const Marker marker) {
|
|||||||
return details::HandlePullDiscardV4<true>(session, state, marker);
|
return details::HandlePullDiscardV4<true>(session, state, marker);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
template <typename TSession>
|
||||||
|
State HandlePullV5(TSession &session, const State state, const Marker marker) {
|
||||||
|
// Using V4 on purpose
|
||||||
|
return HandlePullV4<TSession>(session, state, marker);
|
||||||
|
}
|
||||||
|
|
||||||
template <typename TSession>
|
template <typename TSession>
|
||||||
State HandleDiscardV1(TSession &session, const State state, const Marker marker) {
|
State HandleDiscardV1(TSession &session, const State state, const Marker marker) {
|
||||||
return details::HandlePullDiscardV1<false>(session, state, marker);
|
return details::HandlePullDiscardV1<false>(session, state, marker);
|
||||||
@@ -308,6 +330,12 @@ State HandleDiscardV4(TSession &session, const State state, const Marker marker)
|
|||||||
return details::HandlePullDiscardV4<false>(session, state, marker);
|
return details::HandlePullDiscardV4<false>(session, state, marker);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
template <typename TSession>
|
||||||
|
State HandleDiscardV5(TSession &session, const State state, const Marker marker) {
|
||||||
|
// Using V4 on purpose
|
||||||
|
return HandleDiscardV4<TSession>(session, state, marker);
|
||||||
|
}
|
||||||
|
|
||||||
template <typename TSession>
|
template <typename TSession>
|
||||||
State HandleReset(TSession &session, const Marker marker) {
|
State HandleReset(TSession &session, const Marker marker) {
|
||||||
// IMPORTANT: This implementation of the Bolt RESET command isn't fully
|
// IMPORTANT: This implementation of the Bolt RESET command isn't fully
|
||||||
@@ -360,7 +388,8 @@ State HandleBegin(TSession &session, const State state, const Marker marker) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
try {
|
try {
|
||||||
session.BeginTransaction();
|
session.Configure(extra.ValueMap());
|
||||||
|
session.BeginTransaction(extra.ValueMap());
|
||||||
} catch (const std::exception &e) {
|
} catch (const std::exception &e) {
|
||||||
return HandleFailure(session, e);
|
return HandleFailure(session, e);
|
||||||
}
|
}
|
||||||
@@ -465,4 +494,10 @@ State HandleRoute(TSession &session, const Marker marker) {
|
|||||||
}
|
}
|
||||||
return State::Error;
|
return State::Error;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
template <typename TSession>
|
||||||
|
State HandleLogOff() {
|
||||||
|
// No arguments sent, the user just needs to reauthenticate
|
||||||
|
return State::Init;
|
||||||
|
}
|
||||||
} // namespace memgraph::communication::bolt
|
} // namespace memgraph::communication::bolt
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
// Copyright 2022 Memgraph Ltd.
|
// Copyright 2023 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,6 +18,7 @@
|
|||||||
#include "communication/bolt/v1/state.hpp"
|
#include "communication/bolt/v1/state.hpp"
|
||||||
#include "communication/bolt/v1/value.hpp"
|
#include "communication/bolt/v1/value.hpp"
|
||||||
#include "communication/exceptions.hpp"
|
#include "communication/exceptions.hpp"
|
||||||
|
#include "spdlog/spdlog.h"
|
||||||
#include "utils/likely.hpp"
|
#include "utils/likely.hpp"
|
||||||
#include "utils/logging.hpp"
|
#include "utils/logging.hpp"
|
||||||
|
|
||||||
@@ -27,17 +28,25 @@ namespace details {
|
|||||||
template <typename TSession>
|
template <typename TSession>
|
||||||
std::optional<State> AuthenticateUser(TSession &session, Value &metadata) {
|
std::optional<State> AuthenticateUser(TSession &session, Value &metadata) {
|
||||||
// Get authentication data.
|
// Get authentication data.
|
||||||
|
// From neo4j driver v4.4, fields that have a default value are not sent.
|
||||||
|
// In order to have back-compatibility, the missing fields will be added.
|
||||||
|
|
||||||
auto &data = metadata.ValueMap();
|
auto &data = metadata.ValueMap();
|
||||||
if (!data.count("scheme")) {
|
if (data.empty()) { // Special case auth=None
|
||||||
spdlog::warn("The client didn't supply authentication information!");
|
spdlog::warn("The client didn't supply the authentication scheme! Trying with \"none\"...");
|
||||||
return State::Close;
|
data["scheme"] = "none";
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string username;
|
std::string username;
|
||||||
std::string password;
|
std::string password;
|
||||||
if (data["scheme"].ValueString() == "basic") {
|
if (data["scheme"].ValueString() == "basic") {
|
||||||
if (!data.count("principal") || !data.count("credentials")) {
|
if (!data.count("principal")) { // Special case principal = ""
|
||||||
spdlog::warn("The client didn't supply authentication information!");
|
spdlog::warn("The client didn't supply the principal field! Trying with \"\"...");
|
||||||
return State::Close;
|
data["principal"] = "";
|
||||||
|
}
|
||||||
|
if (!data.count("credentials")) { // Special case credentials = ""
|
||||||
|
spdlog::warn("The client didn't supply the credentials field! Trying with \"\"...");
|
||||||
|
data["credentials"] = "";
|
||||||
}
|
}
|
||||||
username = data["principal"].ValueString();
|
username = data["principal"].ValueString();
|
||||||
password = data["credentials"].ValueString();
|
password = data["credentials"].ValueString();
|
||||||
@@ -106,6 +115,30 @@ std::optional<Value> GetMetadataV4(TSession &session, const Marker marker) {
|
|||||||
return std::nullopt;
|
return std::nullopt;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
auto &data = metadata.ValueMap();
|
||||||
|
if (!data.count("user_agent")) {
|
||||||
|
spdlog::warn("The client didn't supply the user agent!");
|
||||||
|
return std::nullopt;
|
||||||
|
}
|
||||||
|
|
||||||
|
spdlog::info("Client connected '{}'", data.at("user_agent").ValueString());
|
||||||
|
|
||||||
|
return metadata;
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename TSession>
|
||||||
|
std::optional<Value> GetInitDataV5(TSession &session, const Marker marker) {
|
||||||
|
if (marker != Marker::TinyStruct1) [[unlikely]] {
|
||||||
|
spdlog::trace("Expected TinyStruct1 marker, but received 0x{:02X}!", utils::UnderlyingCast(marker));
|
||||||
|
return std::nullopt;
|
||||||
|
}
|
||||||
|
|
||||||
|
Value metadata;
|
||||||
|
if (!session.decoder_.ReadValue(&metadata, Value::Type::Map)) {
|
||||||
|
spdlog::trace("Couldn't read metadata!");
|
||||||
|
return std::nullopt;
|
||||||
|
}
|
||||||
|
|
||||||
const auto &data = metadata.ValueMap();
|
const auto &data = metadata.ValueMap();
|
||||||
if (!data.count("user_agent")) {
|
if (!data.count("user_agent")) {
|
||||||
spdlog::warn("The client didn't supply the user agent!");
|
spdlog::warn("The client didn't supply the user agent!");
|
||||||
@@ -117,6 +150,22 @@ std::optional<Value> GetMetadataV4(TSession &session, const Marker marker) {
|
|||||||
return metadata;
|
return metadata;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
template <typename TSession>
|
||||||
|
std::optional<Value> GetAuthDataV5(TSession &session, const Marker marker) {
|
||||||
|
if (marker != Marker::TinyStruct1) [[unlikely]] {
|
||||||
|
spdlog::trace("Expected TinyStruct1 marker, but received 0x{:02X}!", utils::UnderlyingCast(marker));
|
||||||
|
return std::nullopt;
|
||||||
|
}
|
||||||
|
|
||||||
|
Value metadata;
|
||||||
|
if (!session.decoder_.ReadValue(&metadata, Value::Type::Map)) {
|
||||||
|
spdlog::trace("Couldn't read metadata!");
|
||||||
|
return std::nullopt;
|
||||||
|
}
|
||||||
|
|
||||||
|
return metadata;
|
||||||
|
}
|
||||||
|
|
||||||
template <typename TSession>
|
template <typename TSession>
|
||||||
State SendSuccessMessage(TSession &session) {
|
State SendSuccessMessage(TSession &session) {
|
||||||
// Neo4j's Java driver 4.1.1+ requires connection_id.
|
// Neo4j's Java driver 4.1.1+ requires connection_id.
|
||||||
@@ -180,6 +229,57 @@ State StateInitRunV4(TSession &session, Marker marker, Signature signature) {
|
|||||||
|
|
||||||
return SendSuccessMessage(session);
|
return SendSuccessMessage(session);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
template <typename TSession>
|
||||||
|
State StateInitRunV5(TSession &session, Marker marker, Signature signature) {
|
||||||
|
if (signature == Signature::Noop) [[unlikely]] {
|
||||||
|
SPDLOG_DEBUG("Received NOOP message");
|
||||||
|
return State::Init;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (signature == Signature::Init) {
|
||||||
|
auto maybeMetadata = GetInitDataV5(session, marker);
|
||||||
|
|
||||||
|
if (!maybeMetadata) {
|
||||||
|
return State::Close;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (SendSuccessMessage(session) == State::Close) {
|
||||||
|
return State::Close;
|
||||||
|
}
|
||||||
|
// Stay in Init
|
||||||
|
return State::Init;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (signature == Signature::LogOn) {
|
||||||
|
if (marker != Marker::TinyStruct1) [[unlikely]] {
|
||||||
|
spdlog::trace("Expected TinyStruct1 marker, but received 0x{:02X}!", utils::UnderlyingCast(marker));
|
||||||
|
spdlog::trace(
|
||||||
|
"The client sent malformed data, but we are continuing "
|
||||||
|
"because the official Neo4j Java driver sends malformed "
|
||||||
|
"data. D'oh!");
|
||||||
|
return State::Close;
|
||||||
|
}
|
||||||
|
|
||||||
|
auto maybeMetadata = GetAuthDataV5(session, marker);
|
||||||
|
if (!maybeMetadata) {
|
||||||
|
return State::Close;
|
||||||
|
}
|
||||||
|
auto result = AuthenticateUser(session, *maybeMetadata);
|
||||||
|
if (result) {
|
||||||
|
spdlog::trace("Failed to authenticate, closing connection...");
|
||||||
|
return State::Close;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (SendSuccessMessage(session) == State::Close) {
|
||||||
|
return State::Close;
|
||||||
|
}
|
||||||
|
return State::Idle;
|
||||||
|
}
|
||||||
|
|
||||||
|
spdlog::trace("Expected Init signature, but received 0x{:02X}!", utils::UnderlyingCast(signature));
|
||||||
|
return State::Close;
|
||||||
|
}
|
||||||
} // namespace details
|
} // namespace details
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -208,6 +308,9 @@ State StateInitRun(TSession &session) {
|
|||||||
}
|
}
|
||||||
return details::StateInitRunV4<TSession>(session, marker, signature);
|
return details::StateInitRunV4<TSession>(session, marker, signature);
|
||||||
}
|
}
|
||||||
|
case 5: {
|
||||||
|
return details::StateInitRunV5<TSession>(session, marker, signature);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
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;
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
// Copyright 2022 Memgraph Ltd.
|
// Copyright 2023 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
|
||||||
@@ -342,6 +342,9 @@ std::ostream &operator<<(std::ostream &os, const Vertex &vertex) {
|
|||||||
[&](auto &stream, const auto &pair) { stream << pair.first << ": " << pair.second; });
|
[&](auto &stream, const auto &pair) { stream << pair.first << ": " << pair.second; });
|
||||||
os << "}";
|
os << "}";
|
||||||
}
|
}
|
||||||
|
if (!vertex.element_id.empty()) {
|
||||||
|
os << " element_id: " << vertex.element_id;
|
||||||
|
}
|
||||||
return os << ")";
|
return os << ")";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
// Copyright 2022 Memgraph Ltd.
|
// Copyright 2023 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
|
||||||
@@ -57,6 +57,7 @@ struct Vertex {
|
|||||||
Id id;
|
Id id;
|
||||||
std::vector<std::string> labels;
|
std::vector<std::string> labels;
|
||||||
std::map<std::string, Value> properties;
|
std::map<std::string, Value> properties;
|
||||||
|
std::string element_id;
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -69,6 +70,9 @@ struct Edge {
|
|||||||
Id to;
|
Id to;
|
||||||
std::string type;
|
std::string type;
|
||||||
std::map<std::string, Value> properties;
|
std::map<std::string, Value> properties;
|
||||||
|
std::string element_id;
|
||||||
|
std::string from_element_id;
|
||||||
|
std::string to_element_id;
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -79,6 +83,7 @@ struct UnboundedEdge {
|
|||||||
Id id;
|
Id id;
|
||||||
std::string type;
|
std::string type;
|
||||||
std::map<std::string, Value> properties;
|
std::map<std::string, Value> properties;
|
||||||
|
std::string element_id;
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -107,7 +112,7 @@ struct Path {
|
|||||||
for (uint i = 0; i < edges.size(); i++) {
|
for (uint i = 0; i < edges.size(); i++) {
|
||||||
const auto &e = edges[i];
|
const auto &e = edges[i];
|
||||||
const auto &v = vertices[i + 1];
|
const auto &v = vertices[i + 1];
|
||||||
UnboundedEdge unbounded_edge{e.id, e.type, e.properties};
|
UnboundedEdge unbounded_edge{e.id, e.type, e.properties, e.element_id};
|
||||||
add_element(this->edges, unbounded_edge, e.to == v.id ? 1 : -1, 1);
|
add_element(this->edges, unbounded_edge, e.to == v.id ? 1 : -1, 1);
|
||||||
add_element(this->vertices, v, 1, 0);
|
add_element(this->vertices, v, 1, 0);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
// Copyright 2022 Memgraph Ltd.
|
// Copyright 2023 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
|
||||||
@@ -43,6 +43,7 @@ class Buffer final {
|
|||||||
Buffer(Buffer &&) = delete;
|
Buffer(Buffer &&) = delete;
|
||||||
Buffer &operator=(const Buffer &) = delete;
|
Buffer &operator=(const Buffer &) = delete;
|
||||||
Buffer &operator=(Buffer &&) = delete;
|
Buffer &operator=(Buffer &&) = delete;
|
||||||
|
~Buffer() = default;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This class provides all functions from the buffer that are needed to allow
|
* This class provides all functions from the buffer that are needed to allow
|
||||||
@@ -50,12 +51,13 @@ class Buffer final {
|
|||||||
*/
|
*/
|
||||||
class ReadEnd {
|
class ReadEnd {
|
||||||
public:
|
public:
|
||||||
ReadEnd(Buffer *buffer);
|
explicit ReadEnd(Buffer *buffer);
|
||||||
|
|
||||||
ReadEnd(const ReadEnd &) = delete;
|
ReadEnd(const ReadEnd &) = delete;
|
||||||
ReadEnd(ReadEnd &&) = delete;
|
ReadEnd(ReadEnd &&) = delete;
|
||||||
ReadEnd &operator=(const ReadEnd &) = delete;
|
ReadEnd &operator=(const ReadEnd &) = delete;
|
||||||
ReadEnd &operator=(ReadEnd &&) = delete;
|
ReadEnd &operator=(ReadEnd &&) = delete;
|
||||||
|
~ReadEnd() = default;
|
||||||
|
|
||||||
uint8_t *data();
|
uint8_t *data();
|
||||||
|
|
||||||
@@ -77,12 +79,13 @@ class Buffer final {
|
|||||||
*/
|
*/
|
||||||
class WriteEnd {
|
class WriteEnd {
|
||||||
public:
|
public:
|
||||||
WriteEnd(Buffer *buffer);
|
explicit WriteEnd(Buffer *buffer);
|
||||||
|
|
||||||
WriteEnd(const WriteEnd &) = delete;
|
WriteEnd(const WriteEnd &) = delete;
|
||||||
WriteEnd(WriteEnd &&) = delete;
|
WriteEnd(WriteEnd &&) = delete;
|
||||||
WriteEnd &operator=(const WriteEnd &) = delete;
|
WriteEnd &operator=(const WriteEnd &) = delete;
|
||||||
WriteEnd &operator=(WriteEnd &&) = delete;
|
WriteEnd &operator=(WriteEnd &&) = delete;
|
||||||
|
~WriteEnd() = default;
|
||||||
|
|
||||||
io::network::StreamBuffer Allocate();
|
io::network::StreamBuffer Allocate();
|
||||||
|
|
||||||
|
|||||||
109
src/communication/http/listener.hpp
Normal file
109
src/communication/http/listener.hpp
Normal file
@@ -0,0 +1,109 @@
|
|||||||
|
// Copyright 2023 Memgraph Ltd.
|
||||||
|
//
|
||||||
|
// Use of this software is governed by the Business Source License
|
||||||
|
// included in the file licenses/BSL.txt; by using this file, you agree to be bound by the terms of the Business Source
|
||||||
|
// License, and you may not use this file except in compliance with the Business Source License.
|
||||||
|
//
|
||||||
|
// As of the Change Date specified in that file, in accordance with
|
||||||
|
// the Business Source License, use of this software will be governed
|
||||||
|
// by the Apache License, Version 2.0, included in the file
|
||||||
|
// licenses/APL.txt.
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <list>
|
||||||
|
#include <memory>
|
||||||
|
|
||||||
|
#include <spdlog/spdlog.h>
|
||||||
|
#include <boost/asio/io_context.hpp>
|
||||||
|
#include <boost/asio/ip/tcp.hpp>
|
||||||
|
#include <boost/asio/strand.hpp>
|
||||||
|
#include <boost/beast/core.hpp>
|
||||||
|
|
||||||
|
#include "communication/context.hpp"
|
||||||
|
#include "communication/http/session.hpp"
|
||||||
|
#include "utils/spin_lock.hpp"
|
||||||
|
#include "utils/synchronized.hpp"
|
||||||
|
|
||||||
|
namespace memgraph::communication::http {
|
||||||
|
|
||||||
|
template <class TRequestHandler, typename TSessionContext>
|
||||||
|
class Listener final : public std::enable_shared_from_this<Listener<TRequestHandler, TSessionContext>> {
|
||||||
|
using tcp = boost::asio::ip::tcp;
|
||||||
|
using SessionHandler = Session<TRequestHandler, TSessionContext>;
|
||||||
|
using std::enable_shared_from_this<Listener<TRequestHandler, TSessionContext>>::shared_from_this;
|
||||||
|
|
||||||
|
public:
|
||||||
|
Listener(const Listener &) = delete;
|
||||||
|
Listener(Listener &&) = delete;
|
||||||
|
Listener &operator=(const Listener &) = delete;
|
||||||
|
Listener &operator=(Listener &&) = delete;
|
||||||
|
~Listener() {}
|
||||||
|
|
||||||
|
template <typename... Args>
|
||||||
|
static std::shared_ptr<Listener> Create(Args &&...args) {
|
||||||
|
return std::shared_ptr<Listener>{new Listener(std::forward<Args>(args)...)};
|
||||||
|
}
|
||||||
|
|
||||||
|
// Start accepting incoming connections
|
||||||
|
void Run() { DoAccept(); }
|
||||||
|
tcp::endpoint GetEndpoint() const { return acceptor_.local_endpoint(); }
|
||||||
|
|
||||||
|
private:
|
||||||
|
Listener(boost::asio::io_context &ioc, TSessionContext *session_context, ServerContext *context,
|
||||||
|
tcp::endpoint endpoint)
|
||||||
|
: ioc_(ioc), session_context_(session_context), context_(context), acceptor_(ioc) {
|
||||||
|
boost::beast::error_code ec;
|
||||||
|
|
||||||
|
// Open the acceptor
|
||||||
|
acceptor_.open(endpoint.protocol(), ec);
|
||||||
|
if (ec) {
|
||||||
|
LogError(ec, "open");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Allow address reuse
|
||||||
|
acceptor_.set_option(boost::asio::socket_base::reuse_address(true), ec);
|
||||||
|
if (ec) {
|
||||||
|
LogError(ec, "set_option");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Bind to the server address
|
||||||
|
acceptor_.bind(endpoint, ec);
|
||||||
|
if (ec) {
|
||||||
|
LogError(ec, "bind");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
acceptor_.listen(boost::asio::socket_base::max_listen_connections, ec);
|
||||||
|
if (ec) {
|
||||||
|
LogError(ec, "listen");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
spdlog::info("HTTP server is listening on {}:{}", endpoint.address(), endpoint.port());
|
||||||
|
}
|
||||||
|
|
||||||
|
void DoAccept() {
|
||||||
|
acceptor_.async_accept(ioc_, [shared_this = shared_from_this()](auto ec, auto socket) {
|
||||||
|
shared_this->OnAccept(ec, std::move(socket));
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
void OnAccept(boost::beast::error_code ec, tcp::socket socket) {
|
||||||
|
if (ec) {
|
||||||
|
return LogError(ec, "accept");
|
||||||
|
}
|
||||||
|
|
||||||
|
SessionHandler::Create(std::move(socket), session_context_, *context_)->Run();
|
||||||
|
|
||||||
|
DoAccept();
|
||||||
|
}
|
||||||
|
|
||||||
|
boost::asio::io_context &ioc_;
|
||||||
|
TSessionContext *session_context_;
|
||||||
|
ServerContext *context_;
|
||||||
|
tcp::acceptor acceptor_;
|
||||||
|
};
|
||||||
|
} // namespace memgraph::communication::http
|
||||||
77
src/communication/http/server.hpp
Normal file
77
src/communication/http/server.hpp
Normal file
@@ -0,0 +1,77 @@
|
|||||||
|
// Copyright 2023 Memgraph Ltd.
|
||||||
|
//
|
||||||
|
// Use of this software is governed by the Business Source License
|
||||||
|
// included in the file licenses/BSL.txt; by using this file, you agree to be bound by the terms of the Business Source
|
||||||
|
// License, and you may not use this file except in compliance with the Business Source License.
|
||||||
|
//
|
||||||
|
// As of the Change Date specified in that file, in accordance with
|
||||||
|
// the Business Source License, use of this software will be governed
|
||||||
|
// by the Apache License, Version 2.0, included in the file
|
||||||
|
// licenses/APL.txt.
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <thread>
|
||||||
|
|
||||||
|
#include <boost/asio/io_context.hpp>
|
||||||
|
#include <boost/asio/ip/tcp.hpp>
|
||||||
|
|
||||||
|
#include "communication/http/listener.hpp"
|
||||||
|
#include "io/network/endpoint.hpp"
|
||||||
|
|
||||||
|
namespace memgraph::communication::http {
|
||||||
|
|
||||||
|
template <class TRequestHandler, typename TSessionContext>
|
||||||
|
class Server final {
|
||||||
|
using tcp = boost::asio::ip::tcp;
|
||||||
|
|
||||||
|
public:
|
||||||
|
explicit Server(io::network::Endpoint endpoint, TSessionContext *session_context, ServerContext *context);
|
||||||
|
|
||||||
|
Server(const Server &) = delete;
|
||||||
|
Server(Server &&) = delete;
|
||||||
|
Server &operator=(const Server &) = delete;
|
||||||
|
Server &operator=(Server &&) = delete;
|
||||||
|
|
||||||
|
~Server() {
|
||||||
|
MG_ASSERT(!background_thread_ || (ioc_.stopped() && !background_thread_->joinable()),
|
||||||
|
"Server wasn't shutdown properly");
|
||||||
|
}
|
||||||
|
|
||||||
|
void Start();
|
||||||
|
|
||||||
|
void Shutdown() { ioc_.stop(); }
|
||||||
|
|
||||||
|
void AwaitShutdown() {
|
||||||
|
if (background_thread_ && background_thread_->joinable()) {
|
||||||
|
background_thread_->join();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
bool IsRunning() const { return background_thread_ && !ioc_.stopped(); }
|
||||||
|
tcp::endpoint GetEndpoint() const;
|
||||||
|
|
||||||
|
private:
|
||||||
|
boost::asio::io_context ioc_;
|
||||||
|
|
||||||
|
std::shared_ptr<Listener<TRequestHandler, TSessionContext>> listener_;
|
||||||
|
std::optional<std::thread> background_thread_;
|
||||||
|
};
|
||||||
|
template <class TRequestHandler, typename TSessionContext>
|
||||||
|
Server<TRequestHandler, TSessionContext>::Server(io::network::Endpoint endpoint, TSessionContext *session_context,
|
||||||
|
ServerContext *context)
|
||||||
|
: listener_{Listener<TRequestHandler, TSessionContext>::Create(
|
||||||
|
ioc_, session_context, context,
|
||||||
|
tcp::endpoint{boost::asio::ip::make_address(endpoint.address), endpoint.port})} {}
|
||||||
|
|
||||||
|
template <class TRequestHandler, typename TSessionContext>
|
||||||
|
void Server<TRequestHandler, TSessionContext>::Start() {
|
||||||
|
MG_ASSERT(!background_thread_, "The server was already started!");
|
||||||
|
listener_->Run();
|
||||||
|
background_thread_.emplace([this] { ioc_.run(); });
|
||||||
|
}
|
||||||
|
|
||||||
|
template <class TRequestHandler, typename TSessionContext>
|
||||||
|
boost::asio::ip::tcp::endpoint Server<TRequestHandler, TSessionContext>::GetEndpoint() const {
|
||||||
|
return listener_->GetEndpoint();
|
||||||
|
}
|
||||||
|
} // namespace memgraph::communication::http
|
||||||
193
src/communication/http/session.hpp
Normal file
193
src/communication/http/session.hpp
Normal file
@@ -0,0 +1,193 @@
|
|||||||
|
// Copyright 2023 Memgraph Ltd.
|
||||||
|
//
|
||||||
|
// Use of this software is governed by the Business Source License
|
||||||
|
// included in the file licenses/BSL.txt; by using this file, you agree to be bound by the terms of the Business Source
|
||||||
|
// License, and you may not use this file except in compliance with the Business Source License.
|
||||||
|
//
|
||||||
|
// As of the Change Date specified in that file, in accordance with
|
||||||
|
// the Business Source License, use of this software will be governed
|
||||||
|
// by the Apache License, Version 2.0, included in the file
|
||||||
|
// licenses/APL.txt.
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <deque>
|
||||||
|
#include <functional>
|
||||||
|
#include <memory>
|
||||||
|
#include <optional>
|
||||||
|
#include <string>
|
||||||
|
#include <variant>
|
||||||
|
|
||||||
|
#include <spdlog/spdlog.h>
|
||||||
|
#include <boost/asio/bind_executor.hpp>
|
||||||
|
#include <boost/asio/dispatch.hpp>
|
||||||
|
#include <boost/asio/ip/tcp.hpp>
|
||||||
|
#include <boost/asio/strand.hpp>
|
||||||
|
#include <boost/beast/core/buffers_to_string.hpp>
|
||||||
|
#include <boost/beast/core/stream_traits.hpp>
|
||||||
|
#include <boost/beast/core/tcp_stream.hpp>
|
||||||
|
#include <boost/beast/http.hpp>
|
||||||
|
#include <boost/beast/ssl.hpp>
|
||||||
|
#include <boost/beast/version.hpp>
|
||||||
|
#include <json/json.hpp>
|
||||||
|
|
||||||
|
#include "communication/context.hpp"
|
||||||
|
#include "utils/logging.hpp"
|
||||||
|
#include "utils/variant_helpers.hpp"
|
||||||
|
|
||||||
|
namespace memgraph::communication::http {
|
||||||
|
|
||||||
|
inline constexpr uint16_t kSSLExpirySeconds = 30;
|
||||||
|
inline void LogError(boost::beast::error_code ec, const std::string_view what) {
|
||||||
|
spdlog::warn("HTTP session failed on {}: {}", what, ec.message());
|
||||||
|
}
|
||||||
|
|
||||||
|
template <class TRequestHandler, typename TSessionContext>
|
||||||
|
class Session : public std::enable_shared_from_this<Session<TRequestHandler, TSessionContext>> {
|
||||||
|
using tcp = boost::asio::ip::tcp;
|
||||||
|
using std::enable_shared_from_this<Session<TRequestHandler, TSessionContext>>::shared_from_this;
|
||||||
|
|
||||||
|
public:
|
||||||
|
template <typename... Args>
|
||||||
|
static std::shared_ptr<Session> Create(Args &&...args) {
|
||||||
|
return std::shared_ptr<Session>{new Session{std::forward<Args>(args)...}};
|
||||||
|
}
|
||||||
|
|
||||||
|
void Run() {
|
||||||
|
if (auto *ssl = std::get_if<SSLSocket>(&stream_); ssl != nullptr) {
|
||||||
|
try {
|
||||||
|
boost::beast::get_lowest_layer(*ssl).expires_after(std::chrono::seconds(kSSLExpirySeconds));
|
||||||
|
ssl->handshake(boost::asio::ssl::stream_base::server);
|
||||||
|
} catch (const boost::system::system_error &e) {
|
||||||
|
spdlog::warn("Failed on SSL handshake: {}", e.what());
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// run on the strand
|
||||||
|
boost::asio::dispatch(strand_, [shared_this = shared_from_this()] { shared_this->DoRead(); });
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
using PlainSocket = boost::beast::tcp_stream;
|
||||||
|
using SSLSocket = boost::beast::ssl_stream<boost::beast::tcp_stream>;
|
||||||
|
|
||||||
|
explicit Session(tcp::socket &&socket, TSessionContext *data, ServerContext &context)
|
||||||
|
: stream_(CreateSocket(std::move(socket), context)),
|
||||||
|
handler_(data),
|
||||||
|
strand_{boost::asio::make_strand(GetExecutor())} {}
|
||||||
|
|
||||||
|
std::variant<PlainSocket, SSLSocket> CreateSocket(tcp::socket &&socket, ServerContext &context) {
|
||||||
|
if (context.use_ssl()) {
|
||||||
|
ssl_context_.emplace(context.context_clone());
|
||||||
|
return Session::SSLSocket{std::move(socket), *ssl_context_};
|
||||||
|
}
|
||||||
|
|
||||||
|
return Session::PlainSocket{std::move(socket)};
|
||||||
|
}
|
||||||
|
|
||||||
|
void OnWrite(boost::beast::error_code ec, size_t bytes_transferred) {
|
||||||
|
boost::ignore_unused(bytes_transferred);
|
||||||
|
|
||||||
|
if (ec) {
|
||||||
|
close_ = true;
|
||||||
|
return LogError(ec, "write");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (close_) {
|
||||||
|
DoClose();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
res_ = nullptr;
|
||||||
|
|
||||||
|
DoRead();
|
||||||
|
}
|
||||||
|
|
||||||
|
void DoRead() {
|
||||||
|
req_ = {};
|
||||||
|
|
||||||
|
ExecuteForStream([this](auto &&stream) {
|
||||||
|
boost::beast::get_lowest_layer(stream).expires_after(std::chrono::seconds(kSSLExpirySeconds));
|
||||||
|
|
||||||
|
boost::beast::http::async_read(
|
||||||
|
stream, buffer_, req_,
|
||||||
|
boost::asio::bind_executor(strand_, std::bind_front(&Session::OnRead, shared_from_this())));
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
void OnRead(boost::beast::error_code ec, size_t bytes_transferred) {
|
||||||
|
boost::ignore_unused(bytes_transferred);
|
||||||
|
|
||||||
|
if (ec == boost::beast::http::error::end_of_stream) {
|
||||||
|
DoClose();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (ec) {
|
||||||
|
return LogError(ec, "read");
|
||||||
|
}
|
||||||
|
|
||||||
|
auto async_write = [this](boost::beast::http::response<boost::beast::http::string_body> msg) {
|
||||||
|
ExecuteForStream([this, &msg](auto &&stream) {
|
||||||
|
// The lifetime of the message has to extend
|
||||||
|
// for the duration of the async operation so
|
||||||
|
// we use a shared_ptr to manage it.
|
||||||
|
auto sp = std::make_shared<boost::beast::http::response<boost::beast::http::string_body>>(std::move(msg));
|
||||||
|
|
||||||
|
// Store a type-erased version of the shared
|
||||||
|
// pointer in the class to keep it alive.
|
||||||
|
res_ = sp;
|
||||||
|
// Write the response
|
||||||
|
boost::beast::http::async_write(
|
||||||
|
stream, *sp, boost::asio::bind_executor(strand_, std::bind_front(&Session::OnWrite, shared_from_this())));
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
// handle request
|
||||||
|
handler_.HandleRequest(std::move(req_), async_write);
|
||||||
|
}
|
||||||
|
|
||||||
|
void DoClose() {
|
||||||
|
std::visit(utils::Overloaded{[this](SSLSocket &stream) {
|
||||||
|
boost::beast::get_lowest_layer(stream).expires_after(std::chrono::seconds(30));
|
||||||
|
|
||||||
|
// Perform the SSL shutdown
|
||||||
|
stream.async_shutdown(
|
||||||
|
boost::beast::bind_front_handler(&Session::OnClose, shared_from_this()));
|
||||||
|
},
|
||||||
|
[](PlainSocket &stream) {
|
||||||
|
boost::beast::error_code ec;
|
||||||
|
stream.socket().shutdown(tcp::socket::shutdown_send, ec);
|
||||||
|
}},
|
||||||
|
stream_);
|
||||||
|
}
|
||||||
|
void OnClose(boost::beast::error_code ec) {
|
||||||
|
if (ec) {
|
||||||
|
LogError(ec, "close");
|
||||||
|
}
|
||||||
|
|
||||||
|
// At this point the connection is closed gracefully
|
||||||
|
}
|
||||||
|
|
||||||
|
auto GetExecutor() {
|
||||||
|
return std::visit(utils::Overloaded{[](auto &&stream) { return stream.get_executor(); }}, stream_);
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename F>
|
||||||
|
decltype(auto) ExecuteForStream(F &&fn) {
|
||||||
|
return std::visit(utils::Overloaded{std::forward<F>(fn)}, stream_);
|
||||||
|
}
|
||||||
|
|
||||||
|
std::optional<std::reference_wrapper<boost::asio::ssl::context>> ssl_context_;
|
||||||
|
std::variant<PlainSocket, SSLSocket> stream_;
|
||||||
|
boost::beast::flat_buffer buffer_;
|
||||||
|
|
||||||
|
TRequestHandler handler_;
|
||||||
|
boost::beast::http::request<boost::beast::http::string_body> req_;
|
||||||
|
std::shared_ptr<void> res_;
|
||||||
|
|
||||||
|
boost::asio::strand<boost::beast::tcp_stream::executor_type> strand_;
|
||||||
|
bool close_{false};
|
||||||
|
};
|
||||||
|
} // namespace memgraph::communication::http
|
||||||
@@ -1,4 +1,4 @@
|
|||||||
// Copyright 2022 Memgraph Ltd.
|
// Copyright 2023 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
|
||||||
@@ -39,7 +39,7 @@ namespace memgraph::communication {
|
|||||||
* second, checks all sessions for expiration and shuts them down if they have
|
* second, checks all sessions for expiration and shuts them down if they have
|
||||||
* expired.
|
* expired.
|
||||||
*/
|
*/
|
||||||
template <class TSession, class TSessionData>
|
template <class TSession, class TSessionContext>
|
||||||
class Listener final {
|
class Listener final {
|
||||||
private:
|
private:
|
||||||
// The maximum number of events handled per execution thread is 1. This is
|
// The maximum number of events handled per execution thread is 1. This is
|
||||||
@@ -48,10 +48,10 @@ class Listener final {
|
|||||||
// can take a long time.
|
// can take a long time.
|
||||||
static const int kMaxEvents = 1;
|
static const int kMaxEvents = 1;
|
||||||
|
|
||||||
using SessionHandler = Session<TSession, TSessionData>;
|
using SessionHandler = Session<TSession, TSessionContext>;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
Listener(TSessionData *data, ServerContext *context, int inactivity_timeout_sec, const std::string &service_name,
|
Listener(TSessionContext *data, ServerContext *context, int inactivity_timeout_sec, const std::string &service_name,
|
||||||
size_t workers_count)
|
size_t workers_count)
|
||||||
: data_(data),
|
: data_(data),
|
||||||
alive_(false),
|
alive_(false),
|
||||||
@@ -259,7 +259,7 @@ class Listener final {
|
|||||||
|
|
||||||
io::network::Epoll epoll_;
|
io::network::Epoll epoll_;
|
||||||
|
|
||||||
TSessionData *data_;
|
TSessionContext *data_;
|
||||||
|
|
||||||
utils::SpinLock lock_;
|
utils::SpinLock lock_;
|
||||||
std::vector<std::unique_ptr<SessionHandler>> sessions_;
|
std::vector<std::unique_ptr<SessionHandler>> sessions_;
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
// Copyright 2022 Memgraph Ltd.
|
// Copyright 2023 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
|
||||||
@@ -46,10 +46,10 @@ namespace memgraph::communication {
|
|||||||
* @tparam TSession the server can handle different Sessions, each session
|
* @tparam TSession the server can handle different Sessions, each session
|
||||||
* represents a different protocol so the same network infrastructure
|
* represents a different protocol so the same network infrastructure
|
||||||
* can be used for handling different protocols
|
* can be used for handling different protocols
|
||||||
* @tparam TSessionData the class with objects that will be forwarded to the
|
* @tparam TSessionContext the class with objects that will be forwarded to the
|
||||||
* session
|
* session
|
||||||
*/
|
*/
|
||||||
template <typename TSession, typename TSessionData>
|
template <typename TSession, typename TSessionContext>
|
||||||
class Server final {
|
class Server final {
|
||||||
public:
|
public:
|
||||||
using Socket = io::network::Socket;
|
using Socket = io::network::Socket;
|
||||||
@@ -58,12 +58,12 @@ class Server final {
|
|||||||
* Constructs and binds server to endpoint, operates on session data and
|
* Constructs and binds server to endpoint, operates on session data and
|
||||||
* invokes workers_count workers
|
* invokes workers_count workers
|
||||||
*/
|
*/
|
||||||
Server(const io::network::Endpoint &endpoint, TSessionData *session_data, ServerContext *context,
|
Server(io::network::Endpoint endpoint, TSessionContext *session_context, ServerContext *context,
|
||||||
int inactivity_timeout_sec, const std::string &service_name,
|
int inactivity_timeout_sec, const std::string &service_name,
|
||||||
size_t workers_count = std::thread::hardware_concurrency())
|
size_t workers_count = std::thread::hardware_concurrency())
|
||||||
: alive_(false),
|
: alive_(false),
|
||||||
endpoint_(endpoint),
|
endpoint_(std::move(endpoint)),
|
||||||
listener_(session_data, context, inactivity_timeout_sec, service_name, workers_count),
|
listener_(session_context, context, inactivity_timeout_sec, service_name, workers_count),
|
||||||
service_name_(service_name) {}
|
service_name_(service_name) {}
|
||||||
|
|
||||||
~Server() {
|
~Server() {
|
||||||
@@ -156,7 +156,7 @@ class Server final {
|
|||||||
|
|
||||||
Socket socket_;
|
Socket socket_;
|
||||||
io::network::Endpoint endpoint_;
|
io::network::Endpoint endpoint_;
|
||||||
Listener<TSession, TSessionData> listener_;
|
Listener<TSession, TSessionContext> listener_;
|
||||||
|
|
||||||
const std::string service_name_;
|
const std::string service_name_;
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
// Copyright 2022 Memgraph Ltd.
|
// Copyright 2023 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
|
||||||
@@ -69,10 +69,10 @@ class OutputStream final {
|
|||||||
* sessions. It handles socket ownership, inactivity timeout and protocol
|
* sessions. It handles socket ownership, inactivity timeout and protocol
|
||||||
* wrapping.
|
* wrapping.
|
||||||
*/
|
*/
|
||||||
template <class TSession, class TSessionData>
|
template <class TSession, class TSessionContext>
|
||||||
class Session final {
|
class Session final {
|
||||||
public:
|
public:
|
||||||
Session(io::network::Socket &&socket, TSessionData *data, ServerContext *context, int inactivity_timeout_sec)
|
Session(io::network::Socket &&socket, TSessionContext *data, ServerContext *context, int inactivity_timeout_sec)
|
||||||
: socket_(std::move(socket)),
|
: socket_(std::move(socket)),
|
||||||
output_stream_([this](const uint8_t *data, size_t len, bool have_more) { return Write(data, len, have_more); }),
|
output_stream_([this](const uint8_t *data, size_t len, bool have_more) { return Write(data, len, have_more); }),
|
||||||
session_(data, socket_.endpoint(), input_buffer_.read_end(), &output_stream_),
|
session_(data, socket_.endpoint(), input_buffer_.read_end(), &output_stream_),
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
// Copyright 2022 Memgraph Ltd.
|
// Copyright 2023 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
|
||||||
@@ -30,16 +30,17 @@
|
|||||||
#include "communication/context.hpp"
|
#include "communication/context.hpp"
|
||||||
#include "communication/v2/pool.hpp"
|
#include "communication/v2/pool.hpp"
|
||||||
#include "communication/v2/session.hpp"
|
#include "communication/v2/session.hpp"
|
||||||
|
#include "utils/message.hpp"
|
||||||
#include "utils/spin_lock.hpp"
|
#include "utils/spin_lock.hpp"
|
||||||
#include "utils/synchronized.hpp"
|
#include "utils/synchronized.hpp"
|
||||||
|
|
||||||
namespace memgraph::communication::v2 {
|
namespace memgraph::communication::v2 {
|
||||||
|
|
||||||
template <class TSession, class TSessionData>
|
template <class TSession, class TSessionContext>
|
||||||
class Listener final : public std::enable_shared_from_this<Listener<TSession, TSessionData>> {
|
class Listener final : public std::enable_shared_from_this<Listener<TSession, TSessionContext>> {
|
||||||
using tcp = boost::asio::ip::tcp;
|
using tcp = boost::asio::ip::tcp;
|
||||||
using SessionHandler = Session<TSession, TSessionData>;
|
using SessionHandler = Session<TSession, TSessionContext>;
|
||||||
using std::enable_shared_from_this<Listener<TSession, TSessionData>>::shared_from_this;
|
using std::enable_shared_from_this<Listener<TSession, TSessionContext>>::shared_from_this;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
Listener(const Listener &) = delete;
|
Listener(const Listener &) = delete;
|
||||||
@@ -58,10 +59,10 @@ class Listener final : public std::enable_shared_from_this<Listener<TSession, TS
|
|||||||
bool IsRunning() const noexcept { return alive_.load(std::memory_order_relaxed); }
|
bool IsRunning() const noexcept { return alive_.load(std::memory_order_relaxed); }
|
||||||
|
|
||||||
private:
|
private:
|
||||||
Listener(boost::asio::io_context &io_context, TSessionData *data, ServerContext *server_context,
|
Listener(boost::asio::io_context &io_context, TSessionContext *session_context, ServerContext *server_context,
|
||||||
tcp::endpoint &endpoint, const std::string_view service_name, const uint64_t inactivity_timeout_sec)
|
tcp::endpoint &endpoint, const std::string_view service_name, const uint64_t inactivity_timeout_sec)
|
||||||
: io_context_(io_context),
|
: io_context_(io_context),
|
||||||
data_(data),
|
session_context_(session_context),
|
||||||
server_context_(server_context),
|
server_context_(server_context),
|
||||||
acceptor_(io_context_),
|
acceptor_(io_context_),
|
||||||
endpoint_{endpoint},
|
endpoint_{endpoint},
|
||||||
@@ -110,8 +111,8 @@ class Listener final : public std::enable_shared_from_this<Listener<TSession, TS
|
|||||||
return OnError(ec, "accept");
|
return OnError(ec, "accept");
|
||||||
}
|
}
|
||||||
|
|
||||||
auto session = SessionHandler::Create(std::move(socket), data_, *server_context_, endpoint_, inactivity_timeout_,
|
auto session = SessionHandler::Create(std::move(socket), session_context_, *server_context_, endpoint_,
|
||||||
service_name_);
|
inactivity_timeout_, service_name_);
|
||||||
session->Start();
|
session->Start();
|
||||||
DoAccept();
|
DoAccept();
|
||||||
}
|
}
|
||||||
@@ -122,7 +123,7 @@ class Listener final : public std::enable_shared_from_this<Listener<TSession, TS
|
|||||||
}
|
}
|
||||||
|
|
||||||
boost::asio::io_context &io_context_;
|
boost::asio::io_context &io_context_;
|
||||||
TSessionData *data_;
|
TSessionContext *session_context_;
|
||||||
ServerContext *server_context_;
|
ServerContext *server_context_;
|
||||||
tcp::acceptor acceptor_;
|
tcp::acceptor acceptor_;
|
||||||
|
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
// Copyright 2022 Memgraph Ltd.
|
// Copyright 2023 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
|
||||||
@@ -60,53 +60,32 @@ using ServerEndpoint = boost::asio::ip::tcp::endpoint;
|
|||||||
* @tparam TSession the server can handle different Sessions, each session
|
* @tparam TSession the server can handle different Sessions, each session
|
||||||
* represents a different protocol so the same network infrastructure
|
* represents a different protocol so the same network infrastructure
|
||||||
* can be used for handling different protocols
|
* can be used for handling different protocols
|
||||||
* @tparam TSessionData the class with objects that will be forwarded to the
|
* @tparam TSessionContext the class with objects that will be forwarded to the
|
||||||
* session
|
* session
|
||||||
*/
|
*/
|
||||||
template <typename TSession, typename TSessionData>
|
template <typename TSession, typename TSessionContext>
|
||||||
class Server final {
|
class Server final {
|
||||||
using ServerHandler = Server<TSession, TSessionData>;
|
using ServerHandler = Server<TSession, TSessionContext>;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
/**
|
/**
|
||||||
* Constructs and binds server to endpoint, operates on session data and
|
* Constructs and binds server to endpoint, operates on session data and
|
||||||
* invokes workers_count workers
|
* invokes workers_count workers
|
||||||
*/
|
*/
|
||||||
Server(ServerEndpoint &endpoint, TSessionData *session_data, ServerContext *server_context,
|
Server(ServerEndpoint &endpoint, TSessionContext *session_context, ServerContext *server_context,
|
||||||
const int inactivity_timeout_sec, const std::string_view service_name,
|
int inactivity_timeout_sec, std::string_view service_name,
|
||||||
size_t workers_count = std::thread::hardware_concurrency())
|
size_t workers_count = std::thread::hardware_concurrency());
|
||||||
: endpoint_{endpoint},
|
|
||||||
service_name_{service_name},
|
|
||||||
context_thread_pool_{workers_count},
|
|
||||||
listener_{Listener<TSession, TSessionData>::Create(context_thread_pool_.GetIOContext(), session_data,
|
|
||||||
server_context, endpoint_, service_name_,
|
|
||||||
inactivity_timeout_sec)} {}
|
|
||||||
|
|
||||||
~Server() { MG_ASSERT(!IsRunning(), "Server wasn't shutdown properly"); }
|
~Server();
|
||||||
|
|
||||||
Server(const Server &) = delete;
|
Server(const Server &) = delete;
|
||||||
Server(Server &&) = delete;
|
Server(Server &&) = delete;
|
||||||
Server &operator=(const Server &) = delete;
|
Server &operator=(const Server &) = delete;
|
||||||
Server &operator=(Server &&) = delete;
|
Server &operator=(Server &&) = delete;
|
||||||
|
|
||||||
const auto &Endpoint() const {
|
const auto &Endpoint() const;
|
||||||
MG_ASSERT(IsRunning(), "You can't get the server endpoint when it's not running!");
|
|
||||||
return endpoint_;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool Start() {
|
bool Start();
|
||||||
if (IsRunning()) {
|
|
||||||
spdlog::error("The server is already running");
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
listener_->Start();
|
|
||||||
|
|
||||||
spdlog::info("{} server is fully armed and operational", service_name_);
|
|
||||||
spdlog::info("{} listening on {}", service_name_, endpoint_.address());
|
|
||||||
context_thread_pool_.Run();
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
void Shutdown() {
|
void Shutdown() {
|
||||||
context_thread_pool_.Shutdown();
|
context_thread_pool_.Shutdown();
|
||||||
@@ -115,14 +94,56 @@ class Server final {
|
|||||||
|
|
||||||
void AwaitShutdown() { context_thread_pool_.AwaitShutdown(); }
|
void AwaitShutdown() { context_thread_pool_.AwaitShutdown(); }
|
||||||
|
|
||||||
bool IsRunning() const noexcept { return context_thread_pool_.IsRunning() && listener_->IsRunning(); }
|
bool IsRunning() const noexcept;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
ServerEndpoint endpoint_;
|
ServerEndpoint endpoint_;
|
||||||
std::string service_name_;
|
std::string service_name_;
|
||||||
|
|
||||||
IOContextThreadPool context_thread_pool_;
|
IOContextThreadPool context_thread_pool_;
|
||||||
std::shared_ptr<Listener<TSession, TSessionData>> listener_;
|
std::shared_ptr<Listener<TSession, TSessionContext>> listener_;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
template <typename TSession, typename TSessionContext>
|
||||||
|
Server<TSession, TSessionContext>::~Server() {
|
||||||
|
MG_ASSERT(!IsRunning(), "Server wasn't shutdown properly");
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename TSession, typename TSessionContext>
|
||||||
|
Server<TSession, TSessionContext>::Server(ServerEndpoint &endpoint, TSessionContext *session_context,
|
||||||
|
ServerContext *server_context, const int inactivity_timeout_sec,
|
||||||
|
const std::string_view service_name, size_t workers_count)
|
||||||
|
: endpoint_{endpoint},
|
||||||
|
service_name_{service_name},
|
||||||
|
context_thread_pool_{workers_count},
|
||||||
|
listener_{Listener<TSession, TSessionContext>::Create(context_thread_pool_.GetIOContext(), session_context,
|
||||||
|
server_context, endpoint_, service_name_,
|
||||||
|
inactivity_timeout_sec)} {}
|
||||||
|
|
||||||
|
template <typename TSession, typename TSessionContext>
|
||||||
|
bool Server<TSession, TSessionContext>::Start() {
|
||||||
|
if (IsRunning()) {
|
||||||
|
spdlog::error("The server is already running");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
listener_->Start();
|
||||||
|
|
||||||
|
spdlog::info("{} server is fully armed and operational", service_name_);
|
||||||
|
spdlog::info("{} listening on {}", service_name_, endpoint_.address());
|
||||||
|
context_thread_pool_.Run();
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename TSession, typename TSessionContext>
|
||||||
|
const auto &Server<TSession, TSessionContext>::Endpoint() const {
|
||||||
|
MG_ASSERT(IsRunning(), "You can't get the server endpoint when it's not running!");
|
||||||
|
return endpoint_;
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename TSession, typename TSessionContext>
|
||||||
|
bool Server<TSession, TSessionContext>::IsRunning() const noexcept {
|
||||||
|
return context_thread_pool_.IsRunning() && listener_->IsRunning();
|
||||||
|
}
|
||||||
|
|
||||||
} // namespace memgraph::communication::v2
|
} // namespace memgraph::communication::v2
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
// Copyright 2022 Memgraph Ltd.
|
// Copyright 2023 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
|
||||||
@@ -16,10 +16,12 @@
|
|||||||
#include <cstdint>
|
#include <cstdint>
|
||||||
#include <cstring>
|
#include <cstring>
|
||||||
#include <deque>
|
#include <deque>
|
||||||
|
#include <exception>
|
||||||
#include <functional>
|
#include <functional>
|
||||||
#include <memory>
|
#include <memory>
|
||||||
#include <string>
|
#include <string>
|
||||||
#include <string_view>
|
#include <string_view>
|
||||||
|
#include <unordered_map>
|
||||||
#include <utility>
|
#include <utility>
|
||||||
#include <variant>
|
#include <variant>
|
||||||
|
|
||||||
@@ -41,11 +43,23 @@
|
|||||||
#include <boost/beast/websocket/rfc6455.hpp>
|
#include <boost/beast/websocket/rfc6455.hpp>
|
||||||
#include <boost/system/detail/error_code.hpp>
|
#include <boost/system/detail/error_code.hpp>
|
||||||
|
|
||||||
|
#include "communication/bolt/v1/session.hpp"
|
||||||
|
#include "communication/buffer.hpp"
|
||||||
#include "communication/context.hpp"
|
#include "communication/context.hpp"
|
||||||
#include "communication/exceptions.hpp"
|
#include "communication/exceptions.hpp"
|
||||||
|
#include "dbms/global.hpp"
|
||||||
|
#include "utils/event_counter.hpp"
|
||||||
#include "utils/logging.hpp"
|
#include "utils/logging.hpp"
|
||||||
|
#include "utils/on_scope_exit.hpp"
|
||||||
#include "utils/variant_helpers.hpp"
|
#include "utils/variant_helpers.hpp"
|
||||||
|
|
||||||
|
namespace memgraph::metrics {
|
||||||
|
extern const Event ActiveSessions;
|
||||||
|
extern const Event ActiveTCPSessions;
|
||||||
|
extern const Event ActiveSSLSessions;
|
||||||
|
extern const Event ActiveWebSocketSessions;
|
||||||
|
} // namespace memgraph::metrics
|
||||||
|
|
||||||
namespace memgraph::communication::v2 {
|
namespace memgraph::communication::v2 {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -85,10 +99,10 @@ class OutputStream final {
|
|||||||
* Websocket Sessions. It handles socket ownership, inactivity timeout and protocol
|
* Websocket Sessions. It handles socket ownership, inactivity timeout and protocol
|
||||||
* wrapping.
|
* wrapping.
|
||||||
*/
|
*/
|
||||||
template <typename TSession, typename TSessionData>
|
template <typename TSession, typename TSessionContext>
|
||||||
class WebsocketSession : public std::enable_shared_from_this<WebsocketSession<TSession, TSessionData>> {
|
class WebsocketSession : public std::enable_shared_from_this<WebsocketSession<TSession, TSessionContext>> {
|
||||||
using WebSocket = boost::beast::websocket::stream<boost::beast::tcp_stream>;
|
using WebSocket = boost::beast::websocket::stream<boost::beast::tcp_stream>;
|
||||||
using std::enable_shared_from_this<WebsocketSession<TSession, TSessionData>>::shared_from_this;
|
using std::enable_shared_from_this<WebsocketSession<TSession, TSessionContext>>::shared_from_this;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
template <typename... Args>
|
template <typename... Args>
|
||||||
@@ -96,9 +110,22 @@ class WebsocketSession : public std::enable_shared_from_this<WebsocketSession<TS
|
|||||||
return std::shared_ptr<WebsocketSession>(new WebsocketSession(std::forward<Args>(args)...));
|
return std::shared_ptr<WebsocketSession>(new WebsocketSession(std::forward<Args>(args)...));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifdef MG_ENTERPRISE
|
||||||
|
~WebsocketSession() { session_context_->Delete(session_); }
|
||||||
|
#else
|
||||||
|
~WebsocketSession() = default;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
WebsocketSession(const WebsocketSession &) = delete;
|
||||||
|
WebsocketSession &operator=(const WebsocketSession &) = delete;
|
||||||
|
WebsocketSession(WebsocketSession &&) noexcept = delete;
|
||||||
|
WebsocketSession &operator=(WebsocketSession &&) noexcept = delete;
|
||||||
|
|
||||||
// Start the asynchronous accept operation
|
// Start the asynchronous accept operation
|
||||||
template <class Body, class Allocator>
|
template <class Body, class Allocator>
|
||||||
void DoAccept(boost::beast::http::request<Body, boost::beast::http::basic_fields<Allocator>> req) {
|
void DoAccept(boost::beast::http::request<Body, boost::beast::http::basic_fields<Allocator>> req) {
|
||||||
|
memgraph::metrics::IncrementCounter(memgraph::metrics::ActiveWebSocketSessions);
|
||||||
|
|
||||||
execution_active_ = true;
|
execution_active_ = true;
|
||||||
// Set suggested timeout settings for the websocket
|
// Set suggested timeout settings for the websocket
|
||||||
ws_.set_option(boost::beast::websocket::stream_base::timeout::suggested(boost::beast::role_type::server));
|
ws_.set_option(boost::beast::websocket::stream_base::timeout::suggested(boost::beast::role_type::server));
|
||||||
@@ -139,15 +166,20 @@ class WebsocketSession : public std::enable_shared_from_this<WebsocketSession<TS
|
|||||||
|
|
||||||
private:
|
private:
|
||||||
// Take ownership of the socket
|
// Take ownership of the socket
|
||||||
explicit WebsocketSession(tcp::socket &&socket, TSessionData *data, tcp::endpoint endpoint,
|
explicit WebsocketSession(tcp::socket &&socket, TSessionContext *session_context, tcp::endpoint endpoint,
|
||||||
std::string_view service_name)
|
std::string_view service_name)
|
||||||
: ws_(std::move(socket)),
|
: ws_(std::move(socket)),
|
||||||
strand_{boost::asio::make_strand(ws_.get_executor())},
|
strand_{boost::asio::make_strand(ws_.get_executor())},
|
||||||
output_stream_([this](const uint8_t *data, size_t len, bool /*have_more*/) { return Write(data, len); }),
|
output_stream_([this](const uint8_t *data, size_t len, bool /*have_more*/) { return Write(data, len); }),
|
||||||
session_(data, endpoint, input_buffer_.read_end(), &output_stream_),
|
session_{*session_context, endpoint, input_buffer_.read_end(), &output_stream_},
|
||||||
|
session_context_{session_context},
|
||||||
endpoint_{endpoint},
|
endpoint_{endpoint},
|
||||||
remote_endpoint_{ws_.next_layer().socket().remote_endpoint()},
|
remote_endpoint_{ws_.next_layer().socket().remote_endpoint()},
|
||||||
service_name_{service_name} {}
|
service_name_{service_name} {
|
||||||
|
#ifdef MG_ENTERPRISE
|
||||||
|
session_context_->Register(session_);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
void OnAccept(boost::beast::error_code ec) {
|
void OnAccept(boost::beast::error_code ec) {
|
||||||
if (ec) {
|
if (ec) {
|
||||||
@@ -213,6 +245,10 @@ class WebsocketSession : public std::enable_shared_from_this<WebsocketSession<TS
|
|||||||
if (!IsConnected()) {
|
if (!IsConnected()) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
memgraph::metrics::DecrementCounter(memgraph::metrics::ActiveSessions);
|
||||||
|
memgraph::metrics::DecrementCounter(memgraph::metrics::ActiveWebSocketSessions);
|
||||||
|
|
||||||
if (ec) {
|
if (ec) {
|
||||||
return OnError(ec, "close");
|
return OnError(ec, "close");
|
||||||
}
|
}
|
||||||
@@ -226,6 +262,7 @@ class WebsocketSession : public std::enable_shared_from_this<WebsocketSession<TS
|
|||||||
communication::Buffer input_buffer_;
|
communication::Buffer input_buffer_;
|
||||||
OutputStream output_stream_;
|
OutputStream output_stream_;
|
||||||
TSession session_;
|
TSession session_;
|
||||||
|
TSessionContext *session_context_;
|
||||||
tcp::endpoint endpoint_;
|
tcp::endpoint endpoint_;
|
||||||
tcp::endpoint remote_endpoint_;
|
tcp::endpoint remote_endpoint_;
|
||||||
std::string_view service_name_;
|
std::string_view service_name_;
|
||||||
@@ -237,11 +274,11 @@ class WebsocketSession : public std::enable_shared_from_this<WebsocketSession<TS
|
|||||||
* Sessions. It handles socket ownership, inactivity timeout and protocol
|
* Sessions. It handles socket ownership, inactivity timeout and protocol
|
||||||
* wrapping.
|
* wrapping.
|
||||||
*/
|
*/
|
||||||
template <typename TSession, typename TSessionData>
|
template <typename TSession, typename TSessionContext>
|
||||||
class Session final : public std::enable_shared_from_this<Session<TSession, TSessionData>> {
|
class Session final : public std::enable_shared_from_this<Session<TSession, TSessionContext>> {
|
||||||
using TCPSocket = tcp::socket;
|
using TCPSocket = tcp::socket;
|
||||||
using SSLSocket = boost::asio::ssl::stream<TCPSocket>;
|
using SSLSocket = boost::asio::ssl::stream<TCPSocket>;
|
||||||
using std::enable_shared_from_this<Session<TSession, TSessionData>>::shared_from_this;
|
using std::enable_shared_from_this<Session<TSession, TSessionContext>>::shared_from_this;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
template <typename... Args>
|
template <typename... Args>
|
||||||
@@ -249,22 +286,34 @@ class Session final : public std::enable_shared_from_this<Session<TSession, TSes
|
|||||||
return std::shared_ptr<Session>(new Session(std::forward<Args>(args)...));
|
return std::shared_ptr<Session>(new Session(std::forward<Args>(args)...));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifdef MG_ENTERPRISE
|
||||||
|
~Session() { session_context_->Delete(session_); }
|
||||||
|
#else
|
||||||
|
~Session() = default;
|
||||||
|
#endif
|
||||||
|
|
||||||
Session(const Session &) = delete;
|
Session(const Session &) = delete;
|
||||||
Session(Session &&) = delete;
|
Session(Session &&) = delete;
|
||||||
Session &operator=(const Session &) = delete;
|
Session &operator=(const Session &) = delete;
|
||||||
Session &operator=(Session &&) = delete;
|
Session &operator=(Session &&) = delete;
|
||||||
~Session() = default;
|
|
||||||
|
|
||||||
bool Start() {
|
bool Start() {
|
||||||
if (execution_active_) {
|
if (execution_active_) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
memgraph::metrics::IncrementCounter(memgraph::metrics::ActiveSessions);
|
||||||
|
|
||||||
execution_active_ = true;
|
execution_active_ = true;
|
||||||
timeout_timer_.async_wait(boost::asio::bind_executor(strand_, std::bind(&Session::OnTimeout, shared_from_this())));
|
timeout_timer_.async_wait(boost::asio::bind_executor(strand_, std::bind(&Session::OnTimeout, shared_from_this())));
|
||||||
|
|
||||||
if (std::holds_alternative<SSLSocket>(socket_)) {
|
if (std::holds_alternative<SSLSocket>(socket_)) {
|
||||||
|
utils::OnScopeExit increment_counter(
|
||||||
|
[] { memgraph::metrics::IncrementCounter(memgraph::metrics::ActiveSSLSessions); });
|
||||||
boost::asio::dispatch(strand_, [shared_this = shared_from_this()] { shared_this->DoHandshake(); });
|
boost::asio::dispatch(strand_, [shared_this = shared_from_this()] { shared_this->DoHandshake(); });
|
||||||
} else {
|
} else {
|
||||||
|
utils::OnScopeExit increment_counter(
|
||||||
|
[] { memgraph::metrics::IncrementCounter(memgraph::metrics::ActiveTCPSessions); });
|
||||||
boost::asio::dispatch(strand_, [shared_this = shared_from_this()] { shared_this->DoRead(); });
|
boost::asio::dispatch(strand_, [shared_this = shared_from_this()] { shared_this->DoRead(); });
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
@@ -311,18 +360,23 @@ class Session final : public std::enable_shared_from_this<Session<TSession, TSes
|
|||||||
}
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
explicit Session(tcp::socket &&socket, TSessionData *data, ServerContext &server_context, tcp::endpoint endpoint,
|
explicit Session(tcp::socket &&socket, TSessionContext *session_context, ServerContext &server_context,
|
||||||
const std::chrono::seconds inactivity_timeout_sec, std::string_view service_name)
|
tcp::endpoint endpoint, const std::chrono::seconds inactivity_timeout_sec,
|
||||||
|
std::string_view service_name)
|
||||||
: socket_(CreateSocket(std::move(socket), server_context)),
|
: socket_(CreateSocket(std::move(socket), server_context)),
|
||||||
strand_{boost::asio::make_strand(GetExecutor())},
|
strand_{boost::asio::make_strand(GetExecutor())},
|
||||||
output_stream_([this](const uint8_t *data, size_t len, bool have_more) { return Write(data, len, have_more); }),
|
output_stream_([this](const uint8_t *data, size_t len, bool have_more) { return Write(data, len, have_more); }),
|
||||||
session_(data, endpoint, input_buffer_.read_end(), &output_stream_),
|
session_{*session_context, endpoint, input_buffer_.read_end(), &output_stream_},
|
||||||
data_{data},
|
session_context_{session_context},
|
||||||
endpoint_{endpoint},
|
endpoint_{endpoint},
|
||||||
remote_endpoint_{GetRemoteEndpoint()},
|
remote_endpoint_{GetRemoteEndpoint()},
|
||||||
service_name_{service_name},
|
service_name_{service_name},
|
||||||
timeout_seconds_(inactivity_timeout_sec),
|
timeout_seconds_(inactivity_timeout_sec),
|
||||||
timeout_timer_(GetExecutor()) {
|
timeout_timer_(GetExecutor()) {
|
||||||
|
#ifdef MG_ENTERPRISE
|
||||||
|
// TODO Try to remove Register (see comment at SessionInterface declaration)
|
||||||
|
session_context_->Register(session_);
|
||||||
|
#endif
|
||||||
ExecuteForSocket([](auto &&socket) {
|
ExecuteForSocket([](auto &&socket) {
|
||||||
socket.lowest_layer().set_option(tcp::no_delay(true)); // enable PSH
|
socket.lowest_layer().set_option(tcp::no_delay(true)); // enable PSH
|
||||||
socket.lowest_layer().set_option(boost::asio::socket_base::keep_alive(true)); // enable SO_KEEPALIVE
|
socket.lowest_layer().set_option(boost::asio::socket_base::keep_alive(true)); // enable SO_KEEPALIVE
|
||||||
@@ -373,7 +427,8 @@ class Session final : public std::enable_shared_from_this<Session<TSession, TSes
|
|||||||
spdlog::info("Switching {} to websocket connection", remote_endpoint_);
|
spdlog::info("Switching {} to websocket connection", remote_endpoint_);
|
||||||
if (std::holds_alternative<TCPSocket>(socket_)) {
|
if (std::holds_alternative<TCPSocket>(socket_)) {
|
||||||
auto sock = std::get<TCPSocket>(std::move(socket_));
|
auto sock = std::get<TCPSocket>(std::move(socket_));
|
||||||
WebsocketSession<TSession, TSessionData>::Create(std::move(sock), data_, endpoint_, service_name_)
|
WebsocketSession<TSession, TSessionContext>::Create(std::move(sock), session_context_, endpoint_,
|
||||||
|
service_name_)
|
||||||
->DoAccept(parser.release());
|
->DoAccept(parser.release());
|
||||||
execution_active_ = false;
|
execution_active_ = false;
|
||||||
return;
|
return;
|
||||||
@@ -450,6 +505,14 @@ class Session final : public std::enable_shared_from_this<Session<TSession, TSes
|
|||||||
}
|
}
|
||||||
|
|
||||||
void OnClose(const boost::system::error_code &ec) {
|
void OnClose(const boost::system::error_code &ec) {
|
||||||
|
if (ssl_context_.has_value()) {
|
||||||
|
memgraph::metrics::DecrementCounter(memgraph::metrics::ActiveSSLSessions);
|
||||||
|
} else {
|
||||||
|
memgraph::metrics::DecrementCounter(memgraph::metrics::ActiveTCPSessions);
|
||||||
|
}
|
||||||
|
|
||||||
|
memgraph::metrics::DecrementCounter(memgraph::metrics::ActiveSessions);
|
||||||
|
|
||||||
if (ec) {
|
if (ec) {
|
||||||
return OnError(ec);
|
return OnError(ec);
|
||||||
}
|
}
|
||||||
@@ -465,7 +528,7 @@ class Session final : public std::enable_shared_from_this<Session<TSession, TSes
|
|||||||
if (timeout_timer_.expiry() <= boost::asio::steady_timer::clock_type::now()) {
|
if (timeout_timer_.expiry() <= boost::asio::steady_timer::clock_type::now()) {
|
||||||
// The deadline has passed. Stop the session. The other actors will
|
// The deadline has passed. Stop the session. The other actors will
|
||||||
// terminate as soon as possible.
|
// terminate as soon as possible.
|
||||||
spdlog::info("Shutting down session after {} of inactivity", timeout_seconds_);
|
spdlog::info("Shutting down session after {} seconds of inactivity", timeout_seconds_.count());
|
||||||
DoShutdown();
|
DoShutdown();
|
||||||
} else {
|
} else {
|
||||||
// Put the actor back to sleep.
|
// Put the actor back to sleep.
|
||||||
@@ -504,7 +567,7 @@ class Session final : public std::enable_shared_from_this<Session<TSession, TSes
|
|||||||
communication::Buffer input_buffer_;
|
communication::Buffer input_buffer_;
|
||||||
OutputStream output_stream_;
|
OutputStream output_stream_;
|
||||||
TSession session_;
|
TSession session_;
|
||||||
TSessionData *data_;
|
TSessionContext *session_context_;
|
||||||
tcp::endpoint endpoint_;
|
tcp::endpoint endpoint_;
|
||||||
tcp::endpoint remote_endpoint_;
|
tcp::endpoint remote_endpoint_;
|
||||||
std::string_view service_name_;
|
std::string_view service_name_;
|
||||||
|
|||||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user