Compare commits
95 Commits
separate_r
...
T1312-MG-C
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
3f560fe602 | ||
|
|
c3067d3640 | ||
|
|
a40b18b8aa | ||
|
|
422f9199bd | ||
|
|
667e7f670e | ||
|
|
a100b900c5 | ||
|
|
64bf75117b | ||
|
|
9524a51576 | ||
|
|
fd10d1c9f8 | ||
|
|
22d8ef75e0 | ||
|
|
89585fad1c | ||
|
|
8feefc20b7 | ||
|
|
7b0bafa21e | ||
|
|
de9280b334 | ||
|
|
766ac48261 | ||
|
|
646818a0b4 | ||
|
|
2f4156c2c9 | ||
|
|
61d301310a | ||
|
|
73a554a617 | ||
|
|
06868c8be7 | ||
|
|
bc34a0add6 | ||
|
|
1a3c5af797 | ||
|
|
af4abd4db0 | ||
|
|
f806419b1d | ||
|
|
d278a33f31 | ||
|
|
7fbf5857f2 | ||
|
|
8e3be813ac | ||
|
|
b850a66afd | ||
|
|
0d51a20a02 | ||
|
|
3143c986de | ||
|
|
2fd34489af | ||
|
|
3cc2bc2791 | ||
|
|
96dcfae63e | ||
|
|
1b6a73a021 | ||
|
|
d71b6a5007 | ||
|
|
61ac7e1b11 | ||
|
|
efdf7baea0 | ||
|
|
eb4e2b019d | ||
|
|
1553fcb958 | ||
|
|
bce48361ca | ||
|
|
404cdf05d3 | ||
|
|
b719f0744f | ||
|
|
440838c0e9 | ||
|
|
79a3c5af8e | ||
|
|
bf03b38e39 | ||
|
|
fd63944493 | ||
|
|
6694de2dfa | ||
|
|
5e5f4ffc5d | ||
|
|
060b9d1c16 | ||
|
|
29a505cb38 | ||
|
|
d4fcd745d2 | ||
|
|
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 |
@@ -33,4 +33,4 @@ for file in $modified_files; do
|
||||
fi
|
||||
done;
|
||||
|
||||
return ${FAIL}
|
||||
exit ${FAIL}
|
||||
|
||||
20
.github/workflows/daily_benchmark.yaml
vendored
20
.github/workflows/daily_benchmark.yaml
vendored
@@ -67,7 +67,11 @@ jobs:
|
||||
- name: Run mgbench
|
||||
run: |
|
||||
cd tests/mgbench
|
||||
./benchmark.py vendor-native --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
|
||||
run: |
|
||||
@@ -76,7 +80,19 @@ jobs:
|
||||
source ve3/bin/activate
|
||||
pip install -r requirements.txt
|
||||
./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-number "${{ github.run_number }}" \
|
||||
--head-branch-name "${{ env.BRANCH_NAME }}"
|
||||
|
||||
24
.github/workflows/diff.yaml
vendored
24
.github/workflows/diff.yaml
vendored
@@ -43,7 +43,7 @@ jobs:
|
||||
|
||||
# Build community binaries.
|
||||
cd build
|
||||
cmake -DCMAKE_BUILD_TYPE=release -DMG_ENTERPRISE=OFF ..
|
||||
cmake -DCMAKE_BUILD_TYPE=RelWithDebInfo -DMG_ENTERPRISE=OFF ..
|
||||
make -j$THREADS
|
||||
|
||||
- name: Run unit tests
|
||||
@@ -101,7 +101,7 @@ jobs:
|
||||
echo ${file}
|
||||
if [[ ${file} == *.py ]]; then
|
||||
python3 -m black --check --diff ${file}
|
||||
python3 -m isort --check-only --diff ${file}
|
||||
python3 -m isort --profile black --check-only --diff ${file}
|
||||
fi
|
||||
done
|
||||
|
||||
@@ -229,6 +229,11 @@ jobs:
|
||||
# branches and tags. (default: 1)
|
||||
fetch-depth: 0
|
||||
|
||||
- name: Check e2e service dependencies
|
||||
run: |
|
||||
cd tests/e2e
|
||||
./dependency_check.sh
|
||||
|
||||
- name: Build release binaries
|
||||
run: |
|
||||
# Activate toolchain.
|
||||
@@ -239,12 +244,14 @@ jobs:
|
||||
|
||||
# Build release binaries.
|
||||
cd build
|
||||
cmake -DCMAKE_BUILD_TYPE=release ..
|
||||
cmake -DCMAKE_BUILD_TYPE=RelWithDebInfo ..
|
||||
make -j$THREADS
|
||||
|
||||
- name: Run GQL Behave tests
|
||||
run: |
|
||||
cd tests/gql_behave
|
||||
cd tests
|
||||
./setup.sh /opt/toolchain-v4/activate
|
||||
cd gql_behave
|
||||
./continuous_integration
|
||||
|
||||
- name: Save quality assurance status
|
||||
@@ -275,11 +282,13 @@ jobs:
|
||||
- name: Run stress test (plain)
|
||||
run: |
|
||||
cd tests/stress
|
||||
source ve3/bin/activate
|
||||
./continuous_integration
|
||||
|
||||
- name: Run stress test (SSL)
|
||||
run: |
|
||||
cd tests/stress
|
||||
source ve3/bin/activate
|
||||
./continuous_integration --use-ssl
|
||||
|
||||
- name: Run durability test
|
||||
@@ -342,7 +351,7 @@ jobs:
|
||||
./init
|
||||
# Build only memgraph release binarie.
|
||||
cd build
|
||||
cmake -DCMAKE_BUILD_TYPE=release ..
|
||||
cmake -DCMAKE_BUILD_TYPE=RelWithDebInfo ..
|
||||
make -j$THREADS memgraph
|
||||
|
||||
- name: Run Jepsen tests
|
||||
@@ -410,11 +419,12 @@ jobs:
|
||||
source ve3/bin/activate
|
||||
pip install -r requirements.txt
|
||||
./main.py --benchmark-name "macro_benchmark" \
|
||||
--benchmark-results-path "../../tests/macro_benchmark/.harness_summary" \
|
||||
--benchmark-results "../../tests/macro_benchmark/.harness_summary" \
|
||||
--github-run-id "${{ github.run_id }}" \
|
||||
--github-run-number "${{ github.run_number }}" \
|
||||
--head-branch-name "${{ env.BRANCH_NAME }}"
|
||||
|
||||
# TODO (andi) No need for path flags and for --disk-storage and --in-memory-analytical
|
||||
- name: Run mgbench
|
||||
run: |
|
||||
cd tests/mgbench
|
||||
@@ -427,7 +437,7 @@ jobs:
|
||||
source ve3/bin/activate
|
||||
pip install -r requirements.txt
|
||||
./main.py --benchmark-name "mgbench" \
|
||||
--benchmark-results-path "../../tests/mgbench/benchmark_result.json" \
|
||||
--benchmark-results "../../tests/mgbench/benchmark_result.json" \
|
||||
--github-run-id "${{ github.run_id }}" \
|
||||
--github-run-number "${{ github.run_number }}" \
|
||||
--head-branch-name "${{ env.BRANCH_NAME }}"
|
||||
|
||||
33
.github/workflows/package_all.yaml
vendored
33
.github/workflows/package_all.yaml
vendored
@@ -8,6 +8,13 @@ on:
|
||||
memgraph_version:
|
||||
description: "Memgraph version to upload as. If empty upload is skipped. Format: 'X.Y.Z'"
|
||||
required: false
|
||||
build_type:
|
||||
type: choice
|
||||
description: "Memgraph Build type. Default value is Release."
|
||||
default: 'Release'
|
||||
options:
|
||||
- Release
|
||||
- RelWithDebInfo
|
||||
|
||||
jobs:
|
||||
centos-7:
|
||||
@@ -20,7 +27,7 @@ jobs:
|
||||
fetch-depth: 0 # Required because of release/get_version.py
|
||||
- name: "Build package"
|
||||
run: |
|
||||
./release/package/run.sh package centos-7
|
||||
./release/package/run.sh package centos-7 ${{ github.event.inputs.build_type }}
|
||||
- name: "Upload package"
|
||||
uses: actions/upload-artifact@v3
|
||||
with:
|
||||
@@ -37,7 +44,7 @@ jobs:
|
||||
fetch-depth: 0 # Required because of release/get_version.py
|
||||
- name: "Build package"
|
||||
run: |
|
||||
./release/package/run.sh package centos-9
|
||||
./release/package/run.sh package centos-9 ${{ github.event.inputs.build_type }}
|
||||
- name: "Upload package"
|
||||
uses: actions/upload-artifact@v3
|
||||
with:
|
||||
@@ -54,7 +61,7 @@ jobs:
|
||||
fetch-depth: 0 # Required because of release/get_version.py
|
||||
- name: "Build package"
|
||||
run: |
|
||||
./release/package/run.sh package debian-10
|
||||
./release/package/run.sh package debian-10 ${{ github.event.inputs.build_type }}
|
||||
- name: "Upload package"
|
||||
uses: actions/upload-artifact@v3
|
||||
with:
|
||||
@@ -71,7 +78,7 @@ jobs:
|
||||
fetch-depth: 0 # Required because of release/get_version.py
|
||||
- name: "Build package"
|
||||
run: |
|
||||
./release/package/run.sh package debian-11
|
||||
./release/package/run.sh package debian-11 ${{ github.event.inputs.build_type }}
|
||||
- name: "Upload package"
|
||||
uses: actions/upload-artifact@v3
|
||||
with:
|
||||
@@ -89,7 +96,7 @@ jobs:
|
||||
- name: "Build package"
|
||||
run: |
|
||||
cd release/package
|
||||
./run.sh package debian-11 --for-docker
|
||||
./run.sh package debian-11 ${{ github.event.inputs.build_type }} --for-docker
|
||||
./run.sh docker
|
||||
- name: "Upload package"
|
||||
uses: actions/upload-artifact@v3
|
||||
@@ -107,7 +114,7 @@ jobs:
|
||||
fetch-depth: 0 # Required because of release/get_version.py
|
||||
- name: "Build package"
|
||||
run: |
|
||||
./release/package/run.sh package ubuntu-18.04
|
||||
./release/package/run.sh package ubuntu-18.04 ${{ github.event.inputs.build_type }}
|
||||
- name: "Upload package"
|
||||
uses: actions/upload-artifact@v3
|
||||
with:
|
||||
@@ -124,7 +131,7 @@ jobs:
|
||||
fetch-depth: 0 # Required because of release/get_version.py
|
||||
- name: "Build package"
|
||||
run: |
|
||||
./release/package/run.sh package ubuntu-20.04
|
||||
./release/package/run.sh package ubuntu-20.04 ${{ github.event.inputs.build_type }}
|
||||
- name: "Upload package"
|
||||
uses: actions/upload-artifact@v3
|
||||
with:
|
||||
@@ -141,7 +148,7 @@ jobs:
|
||||
fetch-depth: 0 # Required because of release/get_version.py
|
||||
- name: "Build package"
|
||||
run: |
|
||||
./release/package/run.sh package ubuntu-22.04
|
||||
./release/package/run.sh package ubuntu-22.04 ${{ github.event.inputs.build_type }}
|
||||
- name: "Upload package"
|
||||
uses: actions/upload-artifact@v3
|
||||
with:
|
||||
@@ -158,7 +165,7 @@ jobs:
|
||||
fetch-depth: 0 # Required because of release/get_version.py
|
||||
- name: "Build package"
|
||||
run: |
|
||||
./release/package/run.sh package debian-11 --for-platform
|
||||
./release/package/run.sh package debian-11 ${{ github.event.inputs.build_type }} --for-platform
|
||||
- name: "Upload package"
|
||||
uses: actions/upload-artifact@v3
|
||||
with:
|
||||
@@ -175,7 +182,7 @@ jobs:
|
||||
fetch-depth: 0 # Required because of release/get_version.py
|
||||
- name: "Build package"
|
||||
run: |
|
||||
./release/package/run.sh package fedora-36
|
||||
./release/package/run.sh package fedora-36 ${{ github.event.inputs.build_type }}
|
||||
- name: "Upload package"
|
||||
uses: actions/upload-artifact@v3
|
||||
with:
|
||||
@@ -192,7 +199,7 @@ jobs:
|
||||
fetch-depth: 0 # Required because of release/get_version.py
|
||||
- name: "Build package"
|
||||
run: |
|
||||
./release/package/run.sh package amzn-2
|
||||
./release/package/run.sh package amzn-2 ${{ github.event.inputs.build_type }}
|
||||
- name: "Upload package"
|
||||
uses: actions/upload-artifact@v3
|
||||
with:
|
||||
@@ -209,7 +216,7 @@ jobs:
|
||||
fetch-depth: 0 # Required because of release/get_version.py
|
||||
- name: "Build package"
|
||||
run: |
|
||||
./release/package/run.sh package debian-11-arm
|
||||
./release/package/run.sh package debian-11-arm ${{ github.event.inputs.build_type }}
|
||||
- name: "Upload package"
|
||||
uses: actions/upload-artifact@v3
|
||||
with:
|
||||
@@ -226,7 +233,7 @@ jobs:
|
||||
fetch-depth: 0 # Required because of release/get_version.py
|
||||
- name: "Build package"
|
||||
run: |
|
||||
./release/package/run.sh package ubuntu-22.04-arm
|
||||
./release/package/run.sh package ubuntu-22.04-arm ${{ github.event.inputs.build_type }}
|
||||
- name: "Upload package"
|
||||
uses: actions/upload-artifact@v3
|
||||
with:
|
||||
|
||||
77
.github/workflows/performance_benchmarks.yaml
vendored
Normal file
77
.github/workflows/performance_benchmarks.yaml
vendored
Normal file
@@ -0,0 +1,77 @@
|
||||
name: Run performance benchmarks manually
|
||||
|
||||
on:
|
||||
workflow_dispatch:
|
||||
|
||||
jobs:
|
||||
performance_benchmarks:
|
||||
name: "Performance benchmarks"
|
||||
runs-on: [self-hosted, Linux, X64, Diff, Gen7]
|
||||
env:
|
||||
THREADS: 24
|
||||
MEMGRAPH_ENTERPRISE_LICENSE: ${{ secrets.MEMGRAPH_ENTERPRISE_LICENSE }}
|
||||
MEMGRAPH_ORGANIZATION_NAME: ${{ secrets.MEMGRAPH_ORGANIZATION_NAME }}
|
||||
|
||||
steps:
|
||||
- name: Set up repository
|
||||
uses: actions/checkout@v3
|
||||
with:
|
||||
# Number of commits to fetch. `0` indicates all history for all
|
||||
# branches and tags. (default: 1)
|
||||
fetch-depth: 0
|
||||
|
||||
- name: Build release binaries
|
||||
run: |
|
||||
# Activate toolchain.
|
||||
source /opt/toolchain-v4/activate
|
||||
|
||||
# Initialize dependencies.
|
||||
./init
|
||||
|
||||
# Build only memgraph release binaries.
|
||||
cd build
|
||||
cmake -DCMAKE_BUILD_TYPE=release ..
|
||||
make -j$THREADS
|
||||
|
||||
- name: Get branch name (merge)
|
||||
if: github.event_name != 'pull_request'
|
||||
shell: bash
|
||||
run: echo "BRANCH_NAME=$(echo ${GITHUB_REF#refs/heads/} | tr / -)" >> $GITHUB_ENV
|
||||
|
||||
- name: Get branch name (pull request)
|
||||
if: github.event_name == 'pull_request'
|
||||
shell: bash
|
||||
run: echo "BRANCH_NAME=$(echo ${GITHUB_HEAD_REF} | tr / -)" >> $GITHUB_ENV
|
||||
|
||||
- name: Run benchmarks
|
||||
run: |
|
||||
cd tests/mgbench
|
||||
./benchmark.py vendor-native --num-workers-for-benchmark 12 --export-results benchmark_result.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 benchmark results
|
||||
run: |
|
||||
cd tools/bench-graph-client
|
||||
virtualenv -p python3 ve3
|
||||
source ve3/bin/activate
|
||||
pip install -r requirements.txt
|
||||
./main.py --benchmark-name "mgbench" \
|
||||
--benchmark-results-path "../../tests/mgbench/benchmark_result.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-number "${{ github.run_number }}" \
|
||||
--head-branch-name "${{ env.BRANCH_NAME }}"
|
||||
13
.github/workflows/release_centos8.yaml
vendored
13
.github/workflows/release_centos8.yaml
vendored
@@ -2,6 +2,15 @@ name: Release CentOS 8
|
||||
|
||||
on:
|
||||
workflow_dispatch:
|
||||
inputs:
|
||||
build_type:
|
||||
type: choice
|
||||
description: "Memgraph Build type. Default value is Release."
|
||||
default: 'Release'
|
||||
options:
|
||||
- Release
|
||||
- RelWithDebInfo
|
||||
|
||||
schedule:
|
||||
- cron: "0 22 * * *"
|
||||
|
||||
@@ -33,7 +42,7 @@ jobs:
|
||||
|
||||
# Build community binaries.
|
||||
cd build
|
||||
cmake -DCMAKE_BUILD_TYPE=release -DMG_ENTERPRISE=OFF ..
|
||||
cmake -DCMAKE_BUILD_TYPE=${{ github.event.inputs.build_type }} -DMG_ENTERPRISE=OFF ..
|
||||
make -j$THREADS
|
||||
|
||||
- name: Run unit tests
|
||||
@@ -190,7 +199,7 @@ jobs:
|
||||
|
||||
# Build release binaries.
|
||||
cd build
|
||||
cmake -DCMAKE_BUILD_TYPE=release ..
|
||||
cmake -DCMAKE_BUILD_TYPE=${{ github.event.inputs.build_type }} ..
|
||||
make -j$THREADS
|
||||
|
||||
- name: Create enterprise RPM package
|
||||
|
||||
15
.github/workflows/release_debian10.yaml
vendored
15
.github/workflows/release_debian10.yaml
vendored
@@ -2,6 +2,15 @@ name: Release Debian 10
|
||||
|
||||
on:
|
||||
workflow_dispatch:
|
||||
inputs:
|
||||
build_type:
|
||||
type: choice
|
||||
description: "Memgraph Build type. Default value is Release."
|
||||
default: 'Release'
|
||||
options:
|
||||
- Release
|
||||
- RelWithDebInfo
|
||||
|
||||
schedule:
|
||||
- cron: "0 22 * * *"
|
||||
|
||||
@@ -33,7 +42,7 @@ jobs:
|
||||
|
||||
# Build community binaries.
|
||||
cd build
|
||||
cmake -DCMAKE_BUILD_TYPE=release -DMG_ENTERPRISE=OFF ..
|
||||
cmake -DCMAKE_BUILD_TYPE=${{ github.event.inputs.build_type }} -DMG_ENTERPRISE=OFF ..
|
||||
make -j$THREADS
|
||||
|
||||
- name: Run unit tests
|
||||
@@ -190,7 +199,7 @@ jobs:
|
||||
|
||||
# Build release binaries.
|
||||
cd build
|
||||
cmake -DCMAKE_BUILD_TYPE=release ..
|
||||
cmake -DCMAKE_BUILD_TYPE=${{ github.event.inputs.build_type }} ..
|
||||
make -j$THREADS
|
||||
|
||||
- name: Create enterprise DEB package
|
||||
@@ -322,7 +331,7 @@ jobs:
|
||||
./init
|
||||
# Build only memgraph release binary.
|
||||
cd build
|
||||
cmake -DCMAKE_BUILD_TYPE=release ..
|
||||
cmake -DCMAKE_BUILD_TYPE=${{ github.event.inputs.build_type }} ..
|
||||
make -j$THREADS memgraph
|
||||
|
||||
- name: Run Jepsen tests
|
||||
|
||||
13
.github/workflows/release_ubuntu2004.yaml
vendored
13
.github/workflows/release_ubuntu2004.yaml
vendored
@@ -2,6 +2,15 @@ name: Release Ubuntu 20.04
|
||||
|
||||
on:
|
||||
workflow_dispatch:
|
||||
inputs:
|
||||
build_type:
|
||||
type: choice
|
||||
description: "Memgraph Build type. Default value is Release."
|
||||
default: 'Release'
|
||||
options:
|
||||
- Release
|
||||
- RelWithDebInfo
|
||||
|
||||
schedule:
|
||||
- cron: "0 22 * * *"
|
||||
|
||||
@@ -33,7 +42,7 @@ jobs:
|
||||
|
||||
# Build community binaries.
|
||||
cd build
|
||||
cmake -DCMAKE_BUILD_TYPE=release -DMG_ENTERPRISE=OFF ..
|
||||
cmake -DCMAKE_BUILD_TYPE=${{ github.event.inputs.build_type }} -DMG_ENTERPRISE=OFF ..
|
||||
make -j$THREADS
|
||||
|
||||
- name: Run unit tests
|
||||
@@ -190,7 +199,7 @@ jobs:
|
||||
|
||||
# Build release binaries.
|
||||
cd build
|
||||
cmake -DCMAKE_BUILD_TYPE=release ..
|
||||
cmake -DCMAKE_BUILD_TYPE=${{ github.event.inputs.build_type }} ..
|
||||
make -j$THREADS
|
||||
|
||||
- name: Create enterprise DEB package
|
||||
|
||||
3
.gitignore
vendored
3
.gitignore
vendored
@@ -16,8 +16,7 @@
|
||||
.ycm_extra_conf.pyc
|
||||
.temp/
|
||||
Testing/
|
||||
build
|
||||
build/
|
||||
/build*/
|
||||
release/examples/build
|
||||
cmake-build-*
|
||||
cmake/DownloadProject/
|
||||
|
||||
@@ -15,7 +15,21 @@ repos:
|
||||
hooks:
|
||||
- id: isort
|
||||
name: isort (python)
|
||||
args: ["--profile", "black"]
|
||||
- repo: https://github.com/pre-commit/mirrors-clang-format
|
||||
rev: v13.0.0
|
||||
hooks:
|
||||
- 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
|
||||
|
||||
@@ -42,6 +42,10 @@ endif()
|
||||
|
||||
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)
|
||||
@@ -211,8 +215,8 @@ set(CMAKE_CXX_FLAGS_RELWITHDEBINFO
|
||||
# ** Static linking is allowed only for executables! **
|
||||
set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -static-libgcc -static-libstdc++")
|
||||
|
||||
# Use gold linker to speedup build
|
||||
set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -fuse-ld=gold")
|
||||
# Use lld linker to speedup build
|
||||
add_link_options(-fuse-ld=lld) # TODO: use mold linker
|
||||
|
||||
# release flags
|
||||
set(CMAKE_CXX_FLAGS_RELEASE "-O2 -DNDEBUG")
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
<p align="center">
|
||||
<img width="400px" src="https://uploads-ssl.webflow.com/5e7ceb09657a69bdab054b3a/5e7ceb09657a6937ab054bba_Black_Original%20_Logo.png">
|
||||
<img src="https://public-assets.memgraph.com/github-readme-images/github-memgraph-repo-banner.png">
|
||||
</p>
|
||||
|
||||
---
|
||||
|
||||
@@ -99,6 +99,10 @@ modifications:
|
||||
value: "SNAPSHOT_ISOLATION"
|
||||
override: true
|
||||
|
||||
- name: "storage_mode"
|
||||
value: "IN_MEMORY_TRANSACTIONAL"
|
||||
override: true
|
||||
|
||||
- name: "allow_load_csv"
|
||||
value: "true"
|
||||
override: false
|
||||
@@ -107,6 +111,10 @@ modifications:
|
||||
value: "false"
|
||||
override: true
|
||||
|
||||
- name: "query_callable_mappings_path"
|
||||
value: "/etc/memgraph/apoc_compatibility_mappings.json"
|
||||
override: true
|
||||
|
||||
undocumented:
|
||||
- "flag_file"
|
||||
- "also_log_to_stderr"
|
||||
|
||||
27
config/mappings.json
Normal file
27
config/mappings.json
Normal file
@@ -0,0 +1,27 @@
|
||||
{
|
||||
"dbms.components": "mgps.components",
|
||||
"apoc.util.validate": "mgps.validate",
|
||||
"db.schema.nodeTypeProperties":"schema.node_type_properties",
|
||||
"db.schema.relTypeProperties":"schema.rel_type_properties",
|
||||
"apoc.coll.contains": "collections.contains",
|
||||
"apoc.coll.partition": "collections.partition",
|
||||
"apoc.coll.toSet": "collections.to_set",
|
||||
"apoc.coll.unionAll": "collections.unionAll",
|
||||
"apoc.coll.removeAll": "collections.remove_all",
|
||||
"apoc.coll.union": "collections.union",
|
||||
"apoc.coll.sum": "collections.sum",
|
||||
"apoc.coll.pairs": "collections.pairs",
|
||||
"apoc.map.fromLists": "map.from_lists",
|
||||
"apoc.map.removeKeys": "map.remove_keys",
|
||||
"apoc.map.merge": "map.merge",
|
||||
"apoc.create.nodes": "create.nodes",
|
||||
"apoc.create.removeProperties": "create.remove_properties",
|
||||
"apoc.create.node": "create.node",
|
||||
"apoc.create.removeLabel": "create.remove_label",
|
||||
"apoc.refactor.invert": "refactor.invert",
|
||||
"apoc.refactor.cloneNode": "refactor.clone_node",
|
||||
"apoc.refactor.cloneSubgraph": "refactor.clone_subgraph",
|
||||
"apoc.refactor.cloneSubgraphFromPath": "refactor.clone_subgraph_from_path",
|
||||
"apoc.label.exists": "label.exists"
|
||||
|
||||
}
|
||||
2
environment/.gitignore
vendored
2
environment/.gitignore
vendored
@@ -1,2 +0,0 @@
|
||||
archives
|
||||
build
|
||||
@@ -1,5 +1,10 @@
|
||||
# Memgraph Operating Environments
|
||||
|
||||
## Issues related to build toolchain
|
||||
|
||||
* GCC 11.2 (toolchain-v4) doesn't compile on Fedora 38, multiple definitions of enum issue
|
||||
* spdlog 1.10/11 doesn't work with fmt 10.0.0
|
||||
|
||||
## os
|
||||
|
||||
Under the `os` directory, you can find scripts to install all required system
|
||||
|
||||
@@ -18,7 +18,7 @@ TOOLCHAIN_BUILD_DEPS=(
|
||||
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
|
||||
libedit-devel pcre-devel pcre2-devel automake bison # for swig
|
||||
file
|
||||
openssl-devel
|
||||
gmp-devel
|
||||
|
||||
@@ -20,7 +20,7 @@ TOOLCHAIN_BUILD_DEPS=(
|
||||
curl # snappy
|
||||
readline-devel # cmake and llvm
|
||||
libffi-devel libxml2-devel perl-Digest-MD5 # llvm
|
||||
libedit-devel pcre-devel automake bison # swig
|
||||
libedit-devel pcre-devel pcre2-devel automake bison # swig
|
||||
file
|
||||
openssl-devel
|
||||
gmp-devel
|
||||
|
||||
@@ -17,7 +17,7 @@ TOOLCHAIN_BUILD_DEPS=(
|
||||
expat-devel xz-devel python3-devel texinfo libbabeltrace-devel # for gdb
|
||||
readline-devel # for cmake and llvm
|
||||
libffi-devel libxml2-devel # for llvm
|
||||
libedit-devel pcre-devel automake bison # for swig
|
||||
libedit-devel pcre-devel pcre2-devel automake bison # for swig
|
||||
file
|
||||
openssl-devel
|
||||
gmp-devel
|
||||
|
||||
@@ -24,7 +24,7 @@ TOOLCHAIN_BUILD_DEPS=(
|
||||
libgmp-dev # for gdb
|
||||
gperf # for proxygen
|
||||
git # for fbthrift
|
||||
libedit-dev libpcre3-dev automake bison # for swig
|
||||
libedit-dev libpcre2-dev libpcre3-dev automake bison # for swig
|
||||
)
|
||||
|
||||
TOOLCHAIN_RUN_DEPS=(
|
||||
|
||||
@@ -18,7 +18,7 @@ TOOLCHAIN_BUILD_DEPS=(
|
||||
libcurl4-openssl-dev # for cmake
|
||||
libreadline-dev # for cmake and llvm
|
||||
libffi-dev libxml2-dev # for llvm
|
||||
libedit-dev libpcre3-dev automake bison # for swig
|
||||
libedit-dev libpcre2-dev libpcre3-dev automake bison # for swig
|
||||
curl # snappy
|
||||
file # for libunwind
|
||||
libssl-dev # for libevent
|
||||
|
||||
@@ -18,7 +18,7 @@ TOOLCHAIN_BUILD_DEPS=(
|
||||
libcurl4-openssl-dev # for cmake
|
||||
libreadline-dev # for cmake and llvm
|
||||
libffi-dev libxml2-dev # for llvm
|
||||
libedit-dev libpcre3-dev automake bison # for swig
|
||||
libedit-dev libpcre2-dev libpcre3-dev automake bison # for swig
|
||||
curl # snappy
|
||||
file # for libunwind
|
||||
libssl-dev # for libevent
|
||||
|
||||
@@ -18,7 +18,7 @@ TOOLCHAIN_BUILD_DEPS=(
|
||||
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
|
||||
libedit-devel pcre-devel pcre2-devel automake bison # for swig
|
||||
file
|
||||
openssl-devel
|
||||
gmp-devel
|
||||
|
||||
108
environment/os/fedora-38.sh
Executable file
108
environment/os/fedora-38.sh
Executable file
@@ -0,0 +1,108 @@
|
||||
#!/bin/bash
|
||||
|
||||
set -Eeuo pipefail
|
||||
|
||||
DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" >/dev/null 2>&1 && pwd )"
|
||||
source "$DIR/../util.sh"
|
||||
|
||||
check_operating_system "fedora-38"
|
||||
check_architecture "x86_64"
|
||||
|
||||
TOOLCHAIN_BUILD_DEPS=(
|
||||
coreutils-common gcc gcc-c++ make # generic build tools
|
||||
wget # used for archive download
|
||||
gnupg2 # used for archive signature verification
|
||||
tar gzip bzip2 xz unzip # used for archive unpacking
|
||||
zlib-devel # zlib library used for all builds
|
||||
expat-devel xz-devel python3-devel texinfo libbabeltrace-devel # for gdb
|
||||
curl libcurl-devel # for cmake
|
||||
readline-devel # for cmake and llvm
|
||||
libffi-devel libxml2-devel # for llvm
|
||||
libedit-devel pcre-devel pcre2-devel automake bison # for swig
|
||||
file
|
||||
openssl-devel
|
||||
gmp-devel
|
||||
gperf
|
||||
diffutils
|
||||
libipt libipt-devel # intel
|
||||
patch
|
||||
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 pkgconf-pkg-config # 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 python3-virtualenv python3-virtualenvwrapper python3-pyyaml nmap-ncat # for tests
|
||||
libcurl-devel # mg-requests
|
||||
rpm-build rpmlint # for RPM package building
|
||||
doxygen graphviz # source documentation generators
|
||||
which nodejs golang zip unzip java-11-openjdk-devel # for driver tests
|
||||
sbcl # for custom Lisp C++ preprocessing
|
||||
autoconf # for jemalloc code generation
|
||||
libtool # for protobuf code generation
|
||||
)
|
||||
|
||||
list() {
|
||||
echo "$1"
|
||||
}
|
||||
|
||||
check() {
|
||||
if [ -v LD_LIBRARY_PATH ]; then
|
||||
# On Fedora 38 yum/dnf and python11 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=""
|
||||
fi
|
||||
local missing=""
|
||||
for pkg in $1; do
|
||||
if ! dnf list installed "$pkg" >/dev/null 2>/dev/null; then
|
||||
missing="$pkg $missing"
|
||||
fi
|
||||
done
|
||||
if [ "$missing" != "" ]; then
|
||||
echo "MISSING PACKAGES: $missing"
|
||||
exit 1
|
||||
fi
|
||||
if [ -v OLD_LD_LIBRARY_PATH ]; then
|
||||
echo "Restoring LD_LIBRARY_PATH..."
|
||||
LD_LIBRARY_PATH=${OLD_LD_LIBRARY_PATH}
|
||||
fi
|
||||
}
|
||||
|
||||
install() {
|
||||
cd "$DIR"
|
||||
if [ "$EUID" -ne 0 ]; then
|
||||
echo "Please run as root."
|
||||
exit 1
|
||||
fi
|
||||
# If GitHub Actions runner is installed, append LANG to the environment.
|
||||
# Python related tests 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
|
||||
dnf update -y
|
||||
for pkg in $1; do
|
||||
dnf install -y "$pkg"
|
||||
done
|
||||
}
|
||||
|
||||
deps=$2"[*]"
|
||||
"$1" "${!deps}"
|
||||
@@ -25,7 +25,7 @@ TOOLCHAIN_BUILD_DEPS=(
|
||||
libgmp-dev # for gdb
|
||||
gperf # for proxygen
|
||||
libssl-dev
|
||||
libedit-dev libpcre3-dev automake bison # swig
|
||||
libedit-dev libpcre2-dev libpcre3-dev automake bison # swig
|
||||
)
|
||||
|
||||
TOOLCHAIN_RUN_DEPS=(
|
||||
|
||||
@@ -24,7 +24,7 @@ TOOLCHAIN_BUILD_DEPS=(
|
||||
libgmp-dev # for gdb
|
||||
gperf # for proxygen
|
||||
libssl-dev
|
||||
libedit-dev libpcre3-dev automake bison # for swig
|
||||
libedit-dev libpcre2-dev libpcre3-dev automake bison # for swig
|
||||
)
|
||||
|
||||
TOOLCHAIN_RUN_DEPS=(
|
||||
|
||||
@@ -24,7 +24,7 @@ TOOLCHAIN_BUILD_DEPS=(
|
||||
libgmp-dev # for gdb
|
||||
gperf # for proxygen
|
||||
libssl-dev
|
||||
libedit-dev libpcre3-dev automake bison # for swig
|
||||
libedit-dev libpcre2-dev libpcre3-dev automake bison # for swig
|
||||
)
|
||||
|
||||
TOOLCHAIN_RUN_DEPS=(
|
||||
|
||||
@@ -24,7 +24,7 @@ TOOLCHAIN_BUILD_DEPS=(
|
||||
libgmp-dev # for gdb
|
||||
gperf # for proxygen
|
||||
libssl-dev
|
||||
libedit-dev libpcre3-dev automake bison # for swig
|
||||
libedit-dev libpcre2-dev libpcre3-dev automake bison # for swig
|
||||
)
|
||||
|
||||
TOOLCHAIN_RUN_DEPS=(
|
||||
|
||||
3
environment/toolchain/.gitignore
vendored
3
environment/toolchain/.gitignore
vendored
@@ -1 +1,4 @@
|
||||
archives
|
||||
build
|
||||
output
|
||||
*.tar.gz
|
||||
|
||||
@@ -7,7 +7,7 @@ DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" >/dev/null 2>&1 && pwd )"
|
||||
CPUS=$( grep -c processor < /proc/cpuinfo )
|
||||
cd "$DIR"
|
||||
|
||||
source "$DIR/../util.sh"
|
||||
source "$DIR/../../util.sh"
|
||||
DISTRO="$(operating_system)"
|
||||
|
||||
# toolchain version
|
||||
@@ -30,10 +30,10 @@ LLVM_VERSION=11.0.0
|
||||
SWIG_VERSION=4.0.2 # used only for LLVM compilation
|
||||
|
||||
# Check for the dependencies.
|
||||
echo "ALL BUILD PACKAGES: $($DIR/../os/$DISTRO.sh list TOOLCHAIN_BUILD_DEPS)"
|
||||
$DIR/../os/$DISTRO.sh check TOOLCHAIN_BUILD_DEPS
|
||||
echo "ALL RUN PACKAGES: $($DIR/../os/$DISTRO.sh list TOOLCHAIN_RUN_DEPS)"
|
||||
$DIR/../os/$DISTRO.sh check TOOLCHAIN_RUN_DEPS
|
||||
echo "ALL BUILD PACKAGES: $($DIR/../../os/$DISTRO.sh list TOOLCHAIN_BUILD_DEPS)"
|
||||
$DIR/../../os/$DISTRO.sh check TOOLCHAIN_BUILD_DEPS
|
||||
echo "ALL RUN PACKAGES: $($DIR/../../os/$DISTRO.sh list TOOLCHAIN_RUN_DEPS)"
|
||||
$DIR/../../os/$DISTRO.sh check TOOLCHAIN_RUN_DEPS
|
||||
|
||||
# check installation directory
|
||||
NAME=toolchain-v$TOOLCHAIN_VERSION
|
||||
@@ -442,7 +442,7 @@ In order to be able to run all of these tools you should install the following
|
||||
packages:
|
||||
|
||||
\`\`\`
|
||||
$($DIR/../os/$DISTRO.sh list TOOLCHAIN_RUN_DEPS)
|
||||
$($DIR/../../os/$DISTRO.sh list TOOLCHAIN_RUN_DEPS)
|
||||
\`\`\`
|
||||
|
||||
## Usage
|
||||
@@ -7,7 +7,7 @@ DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" >/dev/null 2>&1 && pwd )"
|
||||
CPUS=$( grep -c processor < /proc/cpuinfo )
|
||||
cd "$DIR"
|
||||
|
||||
source "$DIR/../util.sh"
|
||||
source "$DIR/../../util.sh"
|
||||
DISTRO="$(operating_system)"
|
||||
|
||||
# toolchain version
|
||||
@@ -31,10 +31,10 @@ LLVM_VERSION_LONG=12.0.1-rc4
|
||||
SWIG_VERSION=4.0.2 # used only for LLVM compilation
|
||||
|
||||
# Check for the dependencies.
|
||||
echo "ALL BUILD PACKAGES: $($DIR/../os/$DISTRO.sh list TOOLCHAIN_BUILD_DEPS)"
|
||||
$DIR/../os/$DISTRO.sh check TOOLCHAIN_BUILD_DEPS
|
||||
echo "ALL RUN PACKAGES: $($DIR/../os/$DISTRO.sh list TOOLCHAIN_RUN_DEPS)"
|
||||
$DIR/../os/$DISTRO.sh check TOOLCHAIN_RUN_DEPS
|
||||
echo "ALL BUILD PACKAGES: $($DIR/../../os/$DISTRO.sh list TOOLCHAIN_BUILD_DEPS)"
|
||||
$DIR/../../os/$DISTRO.sh check TOOLCHAIN_BUILD_DEPS
|
||||
echo "ALL RUN PACKAGES: $($DIR/../../os/$DISTRO.sh list TOOLCHAIN_RUN_DEPS)"
|
||||
$DIR/../../os/$DISTRO.sh check TOOLCHAIN_RUN_DEPS
|
||||
|
||||
# check installation directory
|
||||
NAME=toolchain-v$TOOLCHAIN_VERSION
|
||||
@@ -452,7 +452,7 @@ In order to be able to run all of these tools you should install the following
|
||||
packages:
|
||||
|
||||
\`\`\`
|
||||
$($DIR/../os/$DISTRO.sh list TOOLCHAIN_RUN_DEPS)
|
||||
$($DIR/../../os/$DISTRO.sh list TOOLCHAIN_RUN_DEPS)
|
||||
\`\`\`
|
||||
|
||||
## Usage
|
||||
@@ -7,7 +7,7 @@ DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" >/dev/null 2>&1 && pwd )"
|
||||
CPUS=$( grep -c processor < /proc/cpuinfo )
|
||||
cd "$DIR"
|
||||
|
||||
source "$DIR/../util.sh"
|
||||
source "$DIR/../../util.sh"
|
||||
DISTRO="$(operating_system)"
|
||||
|
||||
function log_tool_name () {
|
||||
@@ -51,17 +51,13 @@ CPPCHECK_VERSION=2.6
|
||||
LLVM_VERSION=13.0.0
|
||||
SWIG_VERSION=4.0.2 # used only for LLVM compilation
|
||||
|
||||
# Set the right env script
|
||||
ENV_SCRIPT="$DIR/../os/$DISTRO.sh"
|
||||
# Set the right operating system setup script.
|
||||
ENV_SCRIPT="$DIR/../../os/$DISTRO.sh"
|
||||
if [[ "$for_arm" = true ]]; then
|
||||
ENV_SCRIPT="$DIR/../os/$DISTRO-arm.sh"
|
||||
ENV_SCRIPT="$DIR/../../os/$DISTRO-arm.sh"
|
||||
fi
|
||||
|
||||
# Check for the toolchain build dependencies.
|
||||
echo "ALL BUILD PACKAGES: $(${ENV_SCRIPT} list TOOLCHAIN_BUILD_DEPS)"
|
||||
${ENV_SCRIPT} check TOOLCHAIN_BUILD_DEPS
|
||||
|
||||
# Check for the toolchain run dependencies.
|
||||
echo "ALL RUN PACKAGES: $(${ENV_SCRIPT} list TOOLCHAIN_RUN_DEPS)"
|
||||
${ENV_SCRIPT} check TOOLCHAIN_RUN_DEPS
|
||||
|
||||
@@ -658,7 +654,7 @@ In order to be able to run all of these tools you should install the following
|
||||
packages:
|
||||
|
||||
\`\`\`
|
||||
$($DIR/../os/$ENV_SCRIPT.sh list TOOLCHAIN_RUN_DEPS)
|
||||
$($DIR/../../os/$ENV_SCRIPT.sh list TOOLCHAIN_RUN_DEPS)
|
||||
\`\`\`
|
||||
|
||||
## Usage
|
||||
@@ -4,7 +4,7 @@ diff -ur a/CMakeLists.txt b/CMakeLists.txt
|
||||
@@ -52,9 +52,9 @@
|
||||
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} /EHs-c-")
|
||||
add_definitions(-D_HAS_EXCEPTIONS=0)
|
||||
|
||||
|
||||
- # Disable RTTI.
|
||||
- string(REGEX REPLACE "/GR" "" CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS}")
|
||||
- set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} /GR-")
|
||||
@@ -17,7 +17,7 @@ diff -ur a/CMakeLists.txt b/CMakeLists.txt
|
||||
@@ -77,9 +77,9 @@
|
||||
string(REGEX REPLACE "-fexceptions" "" CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS}")
|
||||
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fno-exceptions")
|
||||
|
||||
|
||||
- # Disable RTTI.
|
||||
- string(REGEX REPLACE "-frtti" "" CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS}")
|
||||
- set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fno-rtti")
|
||||
@@ -25,5 +25,5 @@ diff -ur a/CMakeLists.txt b/CMakeLists.txt
|
||||
+ # string(REGEX REPLACE "-frtti" "" CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS}")
|
||||
+ # set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fno-rtti")
|
||||
endif(CMAKE_CXX_COMPILER_ID STREQUAL "MSVC")
|
||||
|
||||
|
||||
# BUILD_SHARED_LIBS is a standard CMake variable, but we declare it here to make
|
||||
1280
environment/toolchain/v5/build.sh
Executable file
1280
environment/toolchain/v5/build.sh
Executable file
File diff suppressed because it is too large
Load Diff
42
environment/toolchain/v5/clean.sh
Executable file
42
environment/toolchain/v5/clean.sh
Executable file
@@ -0,0 +1,42 @@
|
||||
#!/bin/bash -ex
|
||||
DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" >/dev/null 2>&1 && pwd )"
|
||||
PREFIX=/opt/toolchain-v5
|
||||
|
||||
# NOTE: Often times when versions in the build script are changes, something
|
||||
# doesn't work. To avoid rebuild of the whole toolchain but rebuild specific
|
||||
# lib from 0, just comment specific line under this cript and run it. Don't
|
||||
# forget to comment back to avoid unnecessary deletes next time your run this
|
||||
# cript.
|
||||
|
||||
# rm -rf "$DIR/build"
|
||||
# rm -rf "$DIR/output"
|
||||
|
||||
# rm -rf "$PREFIX/bin/gcc"
|
||||
# rm -rf "$PREFIX/bin/ld.gold"
|
||||
# rm -rf "$PREFIX/bin/gdb"
|
||||
# rm -rf "$PREFIX/bin/cmake"
|
||||
# rm -rf "$PREFIX/bin/clang"
|
||||
# rm -rf "$PREFIX/include/bzlib.h"
|
||||
# rm -rf "$PREFIX/include/fmt"
|
||||
# rm -rf "$PREFIX/include/lz4.h"
|
||||
# rm -rf "$PREFIX/include/lzma.h"
|
||||
# rm -rf "$PREFIX/include/zlib.h"
|
||||
# rm -rf "$PREFIX/include/zstd.h"
|
||||
# rm -rf "$PREFIX/include/jemalloc"
|
||||
# rm -rf "$PREFIX/include/boost"
|
||||
# rm -rf "$PREFIX/include/double-conversion"
|
||||
# rm -rf "$PREFIX/include/gflags"
|
||||
# rm -rf "$PREFIX/include/libunwind.h"
|
||||
# rm -rf "$PREFIX/include/glog"
|
||||
# rm -rf "$PREFIX/include/event2"
|
||||
# rm -rf "$PREFIX/include/sodium.h"
|
||||
# rm -rf "$PREFIX/include/libaio.h"
|
||||
# rm -rf "$PREFIX/include/FlexLexer.h"
|
||||
# rm -rf "$PREFIX/include/snappy.h"
|
||||
# rm -rf "$PREFIX/include/fizz"
|
||||
# rm -rf "$PREFIX/include/folly"
|
||||
# rm -rf "$PREFIX/include/proxygen"
|
||||
# rm -rf "$PREFIX/include/wangle"
|
||||
# rm -rf "$PREFIX/include/thrift"
|
||||
|
||||
# rm -rf "$PREFIX"
|
||||
41
environment/toolchain/v5/folly-2022.01.31.00.patch
Normal file
41
environment/toolchain/v5/folly-2022.01.31.00.patch
Normal file
@@ -0,0 +1,41 @@
|
||||
diff -ur a/folly/CMakeLists.txt b/folly/CMakeLists.txt
|
||||
--- a/folly/CMakeLists.txt 2021-12-12 23:10:42.000000000 +0100
|
||||
+++ b/folly/CMakeLists.txt 2022-02-03 15:19:41.349693134 +0100
|
||||
@@ -28,7 +28,6 @@
|
||||
)
|
||||
|
||||
add_subdirectory(experimental/exception_tracer)
|
||||
-add_subdirectory(logging/example)
|
||||
|
||||
if (PYTHON_EXTENSIONS)
|
||||
# Create tree of symbolic links in structure required for successful
|
||||
diff -ur a/folly/experimental/exception_tracer/ExceptionTracerLib.cpp b/folly/experimental/exception_tracer/ExceptionTracerLib.cpp
|
||||
--- a/folly/experimental/exception_tracer/ExceptionTracerLib.cpp 2021-12-12 23:10:42.000000000 +0100
|
||||
+++ b/folly/experimental/exception_tracer/ExceptionTracerLib.cpp 2022-02-03 15:19:11.003368891 +0100
|
||||
@@ -96,6 +96,7 @@
|
||||
#define __builtin_unreachable()
|
||||
#endif
|
||||
|
||||
+#if 0
|
||||
namespace __cxxabiv1 {
|
||||
|
||||
void __cxa_throw(
|
||||
@@ -154,5 +155,5 @@
|
||||
}
|
||||
|
||||
} // namespace std
|
||||
-
|
||||
+#endif
|
||||
#endif // defined(__GLIBCXX__)
|
||||
diff -ur a/folly/Portability.h b/folly/Portability.h
|
||||
--- a/folly/Portability.h 2021-12-12 23:10:42.000000000 +0100
|
||||
+++ b/folly/Portability.h 2022-02-03 15:19:11.003368891 +0100
|
||||
@@ -566,7 +566,7 @@
|
||||
#define FOLLY_HAS_COROUTINES 0
|
||||
#elif (__cpp_coroutines >= 201703L || __cpp_impl_coroutine >= 201902L) && \
|
||||
(__has_include(<coroutine>) || __has_include(<experimental/coroutine>))
|
||||
-#define FOLLY_HAS_COROUTINES 1
|
||||
+#define FOLLY_HAS_COROUTINES 0
|
||||
// This is mainly to workaround bugs triggered by LTO, when stack allocated
|
||||
// variables in await_suspend end up on a coroutine frame.
|
||||
#define FOLLY_CORO_AWAIT_SUSPEND_NONTRIVIAL_ATTRIBUTES FOLLY_NOINLINE
|
||||
26
environment/toolchain/v5/folly-2023.09.25.00.patch
Normal file
26
environment/toolchain/v5/folly-2023.09.25.00.patch
Normal file
@@ -0,0 +1,26 @@
|
||||
diff --git a/folly/CMakeLists.txt b/folly/CMakeLists.txt
|
||||
index e0e16df..471131e 100644
|
||||
--- a/folly/CMakeLists.txt
|
||||
+++ b/folly/CMakeLists.txt
|
||||
@@ -28,7 +28,7 @@ install(
|
||||
)
|
||||
|
||||
add_subdirectory(experimental/exception_tracer)
|
||||
-add_subdirectory(logging/example)
|
||||
+# add_subdirectory(logging/example)
|
||||
|
||||
if (PYTHON_EXTENSIONS)
|
||||
# Create tree of symbolic links in structure required for successful
|
||||
diff --git a/folly/Portability.h b/folly/Portability.h
|
||||
index 365ef1b..42d24b8 100644
|
||||
--- a/folly/Portability.h
|
||||
+++ b/folly/Portability.h
|
||||
@@ -560,7 +560,7 @@ constexpr auto kCpplibVer = 0;
|
||||
(defined(__cpp_coroutines) && __cpp_coroutines >= 201703L) || \
|
||||
(defined(__cpp_impl_coroutine) && __cpp_impl_coroutine >= 201902L)) && \
|
||||
(__has_include(<coroutine>) || __has_include(<experimental/coroutine>))
|
||||
-#define FOLLY_HAS_COROUTINES 1
|
||||
+#define FOLLY_HAS_COROUTINES 0
|
||||
// This is mainly to workaround bugs triggered by LTO, when stack allocated
|
||||
// variables in await_suspend end up on a coroutine frame.
|
||||
#define FOLLY_CORO_AWAIT_SUSPEND_NONTRIVIAL_ATTRIBUTES FOLLY_NOINLINE
|
||||
29
environment/toolchain/v5/snappy.patch
Normal file
29
environment/toolchain/v5/snappy.patch
Normal file
@@ -0,0 +1,29 @@
|
||||
diff -ur a/CMakeLists.txt b/CMakeLists.txt
|
||||
--- a/CMakeLists.txt 2021-05-05 00:53:34.000000000 +0200
|
||||
+++ b/CMakeLists.txt 2022-01-27 17:18:34.758302398 +0100
|
||||
@@ -52,9 +52,9 @@
|
||||
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} /EHs-c-")
|
||||
add_definitions(-D_HAS_EXCEPTIONS=0)
|
||||
|
||||
- # Disable RTTI.
|
||||
- string(REGEX REPLACE "/GR" "" CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS}")
|
||||
- set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} /GR-")
|
||||
+ # # Disable RTTI.
|
||||
+ # string(REGEX REPLACE "/GR" "" CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS}")
|
||||
+ # set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} /GR-")
|
||||
else(CMAKE_CXX_COMPILER_ID STREQUAL "MSVC")
|
||||
# Use -Wall for clang and gcc.
|
||||
if(NOT CMAKE_CXX_FLAGS MATCHES "-Wall")
|
||||
@@ -77,9 +77,9 @@
|
||||
string(REGEX REPLACE "-fexceptions" "" CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS}")
|
||||
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fno-exceptions")
|
||||
|
||||
- # Disable RTTI.
|
||||
- string(REGEX REPLACE "-frtti" "" CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS}")
|
||||
- set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fno-rtti")
|
||||
+ # # Disable RTTI.
|
||||
+ # string(REGEX REPLACE "-frtti" "" CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS}")
|
||||
+ # set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fno-rtti")
|
||||
endif(CMAKE_CXX_COMPILER_ID STREQUAL "MSVC")
|
||||
|
||||
# BUILD_SHARED_LIBS is a standard CMake variable, but we declare it here to make
|
||||
75
environment/toolchain/v5/xz_pgp.txt
Normal file
75
environment/toolchain/v5/xz_pgp.txt
Normal file
@@ -0,0 +1,75 @@
|
||||
-----BEGIN PGP PUBLIC KEY BLOCK-----
|
||||
|
||||
mQINBEzEOZIBEACxg/IuXERlDB48JBWmF4NxNUuuup1IhJAJyFGFSKh3OGAO2Ard
|
||||
sNuRLjANsFXA7m7P5eTFcG+BoHHuAVYmKnI3PPZtHVLnUt4pGItPczQZ2BE1WpcI
|
||||
ayjGTBJeKItX3Npqg9D/odO9WWS1i3FQPVdrLn0YH37/BA66jeMQCRo7g7GLpaNf
|
||||
IrvYGsqTbxCwsmA37rpE7oyU4Yrf74HT091WBsRIoq/MelhbxTDMR8eu/dUGZQVc
|
||||
Kj3lN55RepwWwUUKyqarY0zMt4HkFJ7v7yRL+Cvzy92Ouv4Wf2FlhNtEs5LE4Tax
|
||||
W0PO5AEmUoKjX87SezQK0f652018b4u6Ex52cY7p+n5TII/UyoowH6+tY8UHo9yb
|
||||
fStrqgNE/mY2bhA6+AwCaOUGsFzVVPTbjtxL3HacUP/jlA1h78V8VTvTs5d55iG7
|
||||
jSqR9o05wje8rwNiXXK0xtiJahyNzL97Kn/DgPSqPIi45G+8nxWSPFM5eunBKRl9
|
||||
vAnsvwrdPRsR6YR3uMHTuVhQX9/CY891MHkaZJ6wydWtKt3yQwJLYqwo5d4DwnUX
|
||||
CduUwSKv+6RmtWI5ZmTQYOcBRcZyGKml9X9Q8iSbm6cnpFXmLrNQwCJN+D3SiYGc
|
||||
MtbltZo0ysPMa6Xj5xFaYqWk/BI4iLb2Gs+ByGo/+a0Eq4XYBMOpitNniQARAQAB
|
||||
tCdMYXNzZSBDb2xsaW4gPGxhc3NlLmNvbGxpbkB0dWthYW5pLm9yZz6JAlEEEwEK
|
||||
ADsCGwMCHgECF4AECwkIBwMVCggFFgIDAQAWIQQ2kMJAzlG0Zw0wrRw47nV9aRhG
|
||||
IAUCYEt9dQUJFxeR4wAKCRA47nV9aRhGIBNDEACxD6vJ+enZwe3IgkJh5JtLsC9b
|
||||
MWCQRlPW1EVMsg96Cb5Rtron1eN1pp1TlzENJu1/C7C/VEsr9WwOPg26Men7fNf/
|
||||
O21QM9IBWd/uB0Pu333WqKh92ESS5x9ST9DrG39nVGSPkQQBMuia72VrA+crPnwT
|
||||
/h/u1IN6/sff5VDIU24rUiqW2Npy733dANruj7Ny0scRXVPltnVdhqwPHt6qNjC1
|
||||
t+/cCnwHgW1BR1RYXBPpB42z/m29dL9rPrG0YPGWs2Bc+EATUICfEE6eIvwfciue
|
||||
IJTjKT9Y9DrogJC2AYFhjC7N04OKdCB2hFs4BjexJwr4X0GJO7LhFl03c951AsIE
|
||||
GHwrucRPB5bo2vmvQ8IvZn7CmtdUJzXv9JlyU6p+MIK1pz7TK6GgSOSffQIXZn6e
|
||||
nUPtm9mEwuncOfmW8/ODYPs1gCWYgyiFJx8h7eEu+M4MxHSFBs7MwXf/Ae2fSp+M
|
||||
P/p198qB8fC5oVBnF95qb0Qi0uc1D+Gb+gpBF+ymMb+s/VBOR3QWiym7AzBrJ62g
|
||||
UnbC9jMLGnSRI+7p7raUfMTgXr5/oQoBw7ExJVltSSRrim2YH/t4CV47mO6dR9J3
|
||||
1RtsTFIRNhz+07XPsETcuCV/dgqeC8fOFLt9MY17Sufhb1DcGy4urZBOIhXcpTV7
|
||||
vHVj5IYH5nYOT49NRYkCOAQTAQIAIgUCTMQ5kgIbAwYLCQgHAwIGFQgCCQoLBBYC
|
||||
AwECHgECF4AACgkQOO51fWkYRiAg4A/7BXKwoRaXrMbMPOW7vuVF7c2IKB2Yqzn1
|
||||
vLBCwuEHkqY237lDcXY4/5LR+1gcZ3Duw1n/BRSm0FBdvyX/JTWiWNSDUkKAO/0l
|
||||
T2Tg44YLrDT3bzwu8dbU9xQt6kH+SCOHvv5Oe4k79l5mro6fF3H1M0bN63x/YoFY
|
||||
ojy09D7/JptY82oR4f/VdKnfZLJcCViCb0wp8SD2NkDAudKg+K+7PD8HlTWklQQg
|
||||
TZdRXxVZKIJeU42aJDqnRbAhJd64YHyClhqut9F5LUmiP5qfLfNhkKDhNOwk2Blr
|
||||
BGBJkSd7wPyzcX4Mun/L6YspHjbeVMt9TD7HQlo+OOd2OjAHCx6pqwkXnzeLPEaE
|
||||
cPdQ1SHgrBViAxX3DNPubLP0Knw8XwFu96EuhHZgexE1W7bB4LFsJyXAc5k1PqPD
|
||||
CLsAauxmvI2OfI7opG/8wyxDvNgoPjG8fZNAgY0REqPC0JnTXChH31IxUmhNotH8
|
||||
tD3DDTZOHw05n5MwwUrEE9xiETVDfFQcMLfxZ9KLz+BC2g1t5LYublRgnCMNJzFg
|
||||
sNUMM02CphABzl/LCLnumr0eyQQ/weV4twEhLwSDmqLYHL0EdYW0Y3CnnU9vmYxQ
|
||||
cXKbstS71sEJJYBBmSBbf9GxkOY8BRNtwVwY0kPgxv1WqdVBiAFvfB+pyAsrax9B
|
||||
3UeB7ZSwRD6JAhwEEAEKAAYFAlS25GwACgkQlbYYGy0z6ew92Q//ZA9/6piQtoW4
|
||||
PwP/1DtWGyKU8hwR+9FG669iPk/dAG+yoEJtFMOUpg/FUFmCX8Bc4oEHsCVyLxKt
|
||||
DcCVUIRcYNSFi5hTZaBEbwsOlDT37gtlfIIu34hhHRccKaLnN/N9gNMNw8wGh9xg
|
||||
Q/KtxZwcbk/bZIlDkKTJkFBRAekdEGAFDWb/AZOy+LQxS8ZAh1eWkfV0i8opmK9k
|
||||
gPXtLE0WSsqtYyGs58z+BFE9NH3tEUwK6jSvtuLwQl4UrICNbKthcpb8WwH6UXzb
|
||||
q3QNSYVOpf/cqRdBJA6bvb/ku/xyKVL08lGmxD9v1b137R7mafDAFPTsvH2Mt/0V
|
||||
YuhtWav3r1Bl9QksDxt2DTS8wiWDUBetGqOVdcw7vBrXPEWDNBmxeJXsiJ7zJlR+
|
||||
9wrJOm6RV2+l1IPxu96EaPS+kTNBijKrhxb67bww8BTEWTd0wcdJmgWRkM8SIstp
|
||||
IKqd0L2TFYph2/NtrBhRg+DIEPJPpSTGsUMcCEXCZPQ+cIdlQKsWpk0tZ62DlvEl
|
||||
r7E+wgUSQolRfx5KrpZifiS2zQlhzdXv28CJhsVbLyw5fUAWUKIH/dCo5NKsNLk2
|
||||
Lc5DH9VWnFgxAAtW290FqeK/4ulMq7Vs1dQSwyHM2Ni3QqqeaiOrh8gbSY5CMLFN
|
||||
Y3HYRwuTYPa3AobsozCzBj0Zdf/6AFe5Ag0ETMQ5kgEQAL/FwKdjxgPxtSpgq1SM
|
||||
zgZtTTyLqhgGD3NZfadHWHYRIL38NDV3JeTA79Y2zj2dj7KQPDT+0aqeizTV2E3j
|
||||
P3iCQ53VOT4consBaQAgKexpptnS+T1DobtICFJ0GGzf0HRj6KO2zSOuOitWPWlU
|
||||
wbvX7M0LLI2+hqlx0jTPqbJFZ/Za6KTtbS6xdCPVUpUqYZQpokEZcwQmUp8Q+lGo
|
||||
JD2sNYCZyap63X/aAOgCGr2RXYddOH5e8vGzGW+mwtCv+WQ9Ay35mGqI5MqkbZd1
|
||||
Qbuv2b1647E/QEEucfRHVbJVKGGPpFMUJtcItyyIt5jo+r9CCL4Cs47dF/9/RNwu
|
||||
NvpvHXUyqMBQdWNZRMx4k/NGD/WviPi9m6mIMui6rOQsSOaqYdcUX4Nq2Orr3Oaz
|
||||
2JPQdUfeI23iot1vK8hxvUCQTV3HfJghizN6spVl0yQOKBiE8miJRgrjHilH3hTb
|
||||
xoo42xDkNAq+CQo3QAm1ibDxKCDq0RcWPjcCRAN/Q5MmpcodpdKkzV0yGIS4g7s5
|
||||
frVrgV/kox2r4/Yxsr8K909+4H82AjTKGX/BmsQFCTAqBk6p7I0zxjIqJ/w33TZB
|
||||
Q0Pn4r3WIlUPafzY6a9/LAvN1fHRxf9SpCByJsszD03Qu5f5TB8gthsdnVmTo7jj
|
||||
iordEKMtw2aEMLzdWWTQ/TNVABEBAAGJAjwEGAEKACYCGwwWIQQ2kMJAzlG0Zw0w
|
||||
rRw47nV9aRhGIAUCYEt9YAUJFxeRzgAKCRA47nV9aRhGIMLtD/9HuKM4pngImcuz
|
||||
YwzQmdv4j26YYyh4jVsKEmVWTiRcehEgUIlrWkCu3qzd5NK+RetS7kJ8MPnzEUfj
|
||||
YbpdC6yrF6n1mSrZZ4VJMkV2ev37bIgXM+Wp1mCAGbjNxQnjn9RabT/gjIqmGuRn
|
||||
AP7RsSeOSuO/gO9h2Pteciz23ussTilB+8cTooQEQQZe6Kv/zukvL+ccSehLHsZ7
|
||||
qVfRUAmtt8nFkXXE+s8jfLfhqstaI2/RJu5witaPcXM8Mnz2E95aASAbZy0eQot9
|
||||
0Pvf07n9yuC3tueTvzvlXx3h5U3yT44tIOmzANIQjay1TGdm+RBJ2ZYyhyLawlZ2
|
||||
NVUXXSp4QZZXPA0UWbF+pb7Q9cdKDNFVuvGBljuea0Yd0T2o+ibDq43HziX9ll+l
|
||||
SXk9mqvW1UcDOaxWrSsm1Gc1O9g3wqH5xHAhtY8GPh/7VgAawskPkmnlkMW6pYPy
|
||||
zibbeISJL1gd1jIT63y6aoVrtNoo+wYJm280ROflh4+5QOo6QJ+jm70fkXSG/qJ5
|
||||
a8/qCPTHkJc/rpkL6/TDQAJURi9RhDAC0gb40HtusbN1LZEA+i0cWTmYXap+DB4Y
|
||||
R4pApilpaG87M+VUokR4xpnx7vTb2MPa7Mdenvi9FEGnKXadmT8038vlfzz5GGUT
|
||||
MlVin9BQPTpdA+PpRiJvKJgVDeAFOg==
|
||||
=asTC
|
||||
-----END PGP PUBLIC KEY BLOCK-----
|
||||
@@ -255,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);
|
||||
}
|
||||
|
||||
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 mgp_vertex *graph_get_vertex_by_id(mgp_graph *g, mgp_vertex_id id, mgp_memory *memory) {
|
||||
@@ -367,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 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) {
|
||||
return MgInvoke<mgp_vertex *>(mgp_vertex_copy, v, memory);
|
||||
}
|
||||
@@ -401,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);
|
||||
}
|
||||
|
||||
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) {
|
||||
return MgInvoke<mgp_properties_iterator *>(mgp_vertex_iter_properties, v, memory);
|
||||
}
|
||||
@@ -437,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);
|
||||
}
|
||||
|
||||
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) {
|
||||
return MgInvoke<mgp_properties_iterator *>(mgp_edge_iter_properties, e, memory);
|
||||
}
|
||||
@@ -455,6 +477,8 @@ inline void path_destroy(mgp_path *path) { mgp_path_destroy(path); }
|
||||
|
||||
inline void path_expand(mgp_path *path, mgp_edge *edge) { MgInvokeVoid(mgp_path_expand, path, edge); }
|
||||
|
||||
inline void path_pop(mgp_path *path) { MgInvokeVoid(mgp_path_pop, path); }
|
||||
|
||||
inline size_t path_size(mgp_path *path) { return MgInvoke<size_t>(mgp_path_size, path); }
|
||||
|
||||
inline mgp_vertex *path_vertex_at(mgp_path *path, size_t index) {
|
||||
|
||||
@@ -333,6 +333,13 @@ class Path:
|
||||
self._vertices.append(edge.end_id)
|
||||
self._edges.append((edge.start_id, edge.end_id, edge.id))
|
||||
|
||||
def pop(self):
|
||||
if not self._edges:
|
||||
raise IndexError("Path contains no relationships.")
|
||||
|
||||
self._vertices.pop()
|
||||
self._edges.pop()
|
||||
|
||||
def vertex_at(self, index: int) -> Vertex:
|
||||
return Vertex(self._vertices[index], self._graph)
|
||||
|
||||
|
||||
@@ -543,6 +543,10 @@ void mgp_path_destroy(struct mgp_path *path);
|
||||
/// Return mgp_error::MGP_ERROR_UNABLE_TO_ALLOCATE if unable to allocate memory for path extension.
|
||||
enum mgp_error mgp_path_expand(struct mgp_path *path, struct mgp_edge *edge);
|
||||
|
||||
/// Remove the last node and the last relationship from the path.
|
||||
/// Return mgp_error::MGP_ERROR_OUT_OF_RANGE if the path contains no relationships.
|
||||
enum mgp_error mgp_path_pop(struct mgp_path *path);
|
||||
|
||||
/// Get the number of edges in a mgp_path.
|
||||
/// Current implementation always returns without errors.
|
||||
enum mgp_error mgp_path_size(struct mgp_path *path, size_t *result);
|
||||
@@ -647,6 +651,12 @@ struct mgp_vertex_id {
|
||||
/// Get the ID of given vertex.
|
||||
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.
|
||||
/// 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
|
||||
@@ -664,6 +674,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,
|
||||
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.
|
||||
/// 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.
|
||||
@@ -814,6 +833,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.
|
||||
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.
|
||||
/// 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
|
||||
@@ -864,6 +892,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,
|
||||
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.
|
||||
/// 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
|
||||
|
||||
668
include/mgp.hpp
668
include/mgp.hpp
File diff suppressed because it is too large
Load Diff
@@ -479,6 +479,12 @@ class Properties:
|
||||
except KeyError:
|
||||
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:
|
||||
"""Type of an Edge."""
|
||||
@@ -977,6 +983,24 @@ class Path:
|
||||
self._vertices = None
|
||||
self._edges = None
|
||||
|
||||
def pop(self):
|
||||
"""
|
||||
Remove the last node and the last relationship from the path.
|
||||
|
||||
Raises:
|
||||
InvalidContextError: If using an invalid `Path` instance
|
||||
OutOfRangeError: If the path contains no relationships.
|
||||
|
||||
Examples:
|
||||
```path.pop()```
|
||||
"""
|
||||
if not self.is_valid():
|
||||
raise InvalidContextError()
|
||||
self._path.pop()
|
||||
# Invalidate our cached tuples
|
||||
self._vertices = None
|
||||
self._edges = None
|
||||
|
||||
@property
|
||||
def vertices(self) -> typing.Tuple[Vertex, ...]:
|
||||
"""
|
||||
@@ -1017,6 +1041,10 @@ class Path:
|
||||
self._edges = tuple(Edge(self._path.edge_at(i)) for i in range(num_edges))
|
||||
return self._edges
|
||||
|
||||
@property
|
||||
def length(self) -> int:
|
||||
return self._path.size()
|
||||
|
||||
|
||||
class Record:
|
||||
"""Represents a record of resulting field values."""
|
||||
|
||||
@@ -929,6 +929,25 @@ class Path:
|
||||
self._vertices = None
|
||||
self._edges = None
|
||||
|
||||
def pop(self):
|
||||
"""
|
||||
Remove the last node and the last relationship from the path.
|
||||
|
||||
Raises:
|
||||
InvalidContextError: If using an invalid `Path` instance
|
||||
OutOfRangeError: If the path contains no relationships.
|
||||
|
||||
Examples:
|
||||
```path.pop()```
|
||||
"""
|
||||
if not self.is_valid():
|
||||
raise InvalidContextError()
|
||||
self._path.pop()
|
||||
|
||||
# Invalidate cached tuples
|
||||
self._vertices = None
|
||||
self._edges = None
|
||||
|
||||
@property
|
||||
def vertices(self) -> typing.Tuple[Vertex, ...]:
|
||||
"""
|
||||
|
||||
@@ -261,3 +261,7 @@ import_external_library(librdtsc STATIC
|
||||
|
||||
# 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)
|
||||
|
||||
@@ -123,6 +123,7 @@ declare -A primary_urls=(
|
||||
["pulsar"]="http://$local_cache_host/git/pulsar.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
|
||||
@@ -140,7 +141,7 @@ declare -A secondary_urls=(
|
||||
["rocksdb"]="https://github.com/facebook/rocksdb.git"
|
||||
["mgclient"]="https://github.com/memgraph/mgclient.git"
|
||||
["pymgclient"]="https://github.com/memgraph/pymgclient.git"
|
||||
["mgconsole"]="http://github.com/memgraph/mgconsole.git"
|
||||
["mgconsole"]="https://github.com/memgraph/mgconsole.git"
|
||||
["spdlog"]="https://github.com/gabime/spdlog"
|
||||
["nlohmann"]="https://raw.githubusercontent.com/nlohmann/json/4f8fba14066156b73f1189a2b8bd568bde5284c5/single_include/nlohmann/json.hpp"
|
||||
["neo4j"]="https://dist.neo4j.org/neo4j-community-5.6.0-unix.tar.gz"
|
||||
@@ -149,6 +150,7 @@ declare -A secondary_urls=(
|
||||
["pulsar"]="https://github.com/apache/pulsar.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
|
||||
@@ -246,3 +248,7 @@ 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
|
||||
which competes (or might reasonably be expected to
|
||||
compete) with the Licensed Work.
|
||||
CHANGE DATE: 2027-02-08
|
||||
CHANGE DATE: 2027-13-09
|
||||
CHANGE LICENSE: Apache License, Version 2.0
|
||||
|
||||
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.
|
||||
@@ -1,4 +1,4 @@
|
||||
// Copyright 2022 Memgraph Ltd.
|
||||
// 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
|
||||
@@ -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) {
|
||||
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;
|
||||
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) {
|
||||
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);
|
||||
|
||||
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) {
|
||||
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;
|
||||
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) {
|
||||
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,
|
||||
{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 {
|
||||
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)},
|
||||
{}, module, memory);
|
||||
@@ -87,7 +107,11 @@ extern "C" int mgp_init_module(struct mgp_module *module, struct mgp_memory *mem
|
||||
}
|
||||
|
||||
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::Parameter("int", mgp::Type::Int), mgp::Parameter("int", mgp::Type::Int, (int64_t)3)}, module,
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
/etc/memgraph/memgraph.conf
|
||||
/etc/memgraph/apoc_compatibility_mappings.json
|
||||
/etc/memgraph/auth_module/ldap.example.yaml
|
||||
/etc/logrotate.d/memgraph
|
||||
|
||||
@@ -11,6 +11,12 @@ SUPPORTED_OS=(
|
||||
amzn-2
|
||||
)
|
||||
|
||||
SUPPORTED_BUILD_TYPES=(
|
||||
Debug
|
||||
Release
|
||||
RelWithDebInfo
|
||||
)
|
||||
|
||||
PROJECT_ROOT="$SCRIPT_DIR/../.."
|
||||
TOOLCHAIN_VERSION="toolchain-v4"
|
||||
ACTIVATE_TOOLCHAIN="source /opt/${TOOLCHAIN_VERSION}/activate"
|
||||
@@ -18,14 +24,16 @@ HOST_OUTPUT_DIR="$PROJECT_ROOT/build/output"
|
||||
|
||||
print_help () {
|
||||
# TODO(gitbuda): Update the release/package/run.sh help
|
||||
echo "$0 init|package|docker|test {os} [--for-docker|--for-platform]"
|
||||
echo "$0 init|package|docker|test {os} {build_type} [--for-docker|--for-platform]"
|
||||
echo ""
|
||||
echo " OSs: ${SUPPORTED_OS[*]}"
|
||||
echo " Build types: ${SUPPORTED_BUILD_TYPES[*]}"
|
||||
exit 1
|
||||
}
|
||||
|
||||
make_package () {
|
||||
os="$1"
|
||||
build_type="$2"
|
||||
|
||||
build_container="mgbuild_$os"
|
||||
echo "Building Memgraph for $os on $build_container..."
|
||||
@@ -44,10 +52,10 @@ make_package () {
|
||||
package_command=" cpack -G DEB --config ../CPackConfig.cmake "
|
||||
fi
|
||||
telemetry_id_override_flag=""
|
||||
if [[ "$#" -gt 1 ]]; then
|
||||
if [[ "$2" == "--for-docker" ]]; then
|
||||
if [[ "$#" -gt 2 ]]; then
|
||||
if [[ "$3" == "--for-docker" ]]; then
|
||||
telemetry_id_override_flag=" -DMG_TELEMETRY_ID_OVERRIDE=DOCKER "
|
||||
elif [[ "$2" == "--for-platform" ]]; then
|
||||
elif [[ "$3" == "--for-platform" ]]; then
|
||||
telemetry_id_override_flag=" -DMG_TELEMETRY_ID_OVERRIDE=DOCKER-PLATFORM"
|
||||
else
|
||||
print_help
|
||||
@@ -89,9 +97,9 @@ make_package () {
|
||||
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
|
||||
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=$build_type -DMG_ARCH="ARM64" $telemetry_id_override_flag .."
|
||||
else
|
||||
docker exec "$build_container" bash -c "cd $container_build_dir && $ACTIVATE_TOOLCHAIN && cmake -DCMAKE_BUILD_TYPE=release $telemetry_id_override_flag .."
|
||||
docker exec "$build_container" bash -c "cd $container_build_dir && $ACTIVATE_TOOLCHAIN && cmake -DCMAKE_BUILD_TYPE=$build_type $telemetry_id_override_flag .."
|
||||
fi
|
||||
# ' is used instead of " because we need to run make within the allowed
|
||||
# container resources.
|
||||
@@ -141,20 +149,34 @@ case "$1" in
|
||||
|
||||
package)
|
||||
shift 1
|
||||
if [[ "$#" -lt 1 ]]; then
|
||||
if [[ "$#" -lt 2 ]]; then
|
||||
print_help
|
||||
fi
|
||||
os="$1"
|
||||
shift 1
|
||||
build_type="$2"
|
||||
shift 2
|
||||
is_os_ok=false
|
||||
for supported_os in "${SUPPORTED_OS[@]}"; do
|
||||
if [[ "$supported_os" == "${os}" ]]; then
|
||||
is_os_ok=true
|
||||
break
|
||||
fi
|
||||
done
|
||||
if [[ "$is_os_ok" == true ]]; then
|
||||
make_package "$os" "$@"
|
||||
is_build_type_ok=false
|
||||
for supported_build_type in "${SUPPORTED_BUILD_TYPES[@]}"; do
|
||||
if [[ "$supported_build_type" == "${build_type}" ]]; then
|
||||
is_build_type_ok=true
|
||||
break
|
||||
fi
|
||||
done
|
||||
if [[ "$is_os_ok" == true && "$is_build_type_ok" == true ]]; then
|
||||
make_package "$os" "$build_type" "$@"
|
||||
else
|
||||
if [[ "$is_os_ok" == false ]]; then
|
||||
echo "Unsupported OS: $os"
|
||||
elif [[ "$is_build_type_ok" == false ]]; then
|
||||
echo "Unsupported build type: $build_type"
|
||||
fi
|
||||
print_help
|
||||
fi
|
||||
;;
|
||||
|
||||
@@ -132,6 +132,7 @@ echo "Don't forget to switch to the 'memgraph' user to use Memgraph" || exit 1
|
||||
# Override CPACK_RPM_ABSOLUTE_INSTALL_FILES with our %config(noreplace), cpack
|
||||
# uses plain %config.
|
||||
%config(noreplace) "/etc/memgraph/memgraph.conf"
|
||||
%config(noreplace) "/etc/memgraph/apoc_compatibility_mappings.json"
|
||||
%config(noreplace) "/etc/memgraph/auth_module/ldap.example.yaml"
|
||||
%config(noreplace) "/etc/logrotate.d/memgraph"
|
||||
|
||||
|
||||
@@ -18,6 +18,10 @@ add_subdirectory(rpc)
|
||||
add_subdirectory(license)
|
||||
add_subdirectory(auth)
|
||||
add_subdirectory(audit)
|
||||
add_subdirectory(dbms)
|
||||
add_subdirectory(flags)
|
||||
add_subdirectory(distributed)
|
||||
add_subdirectory(replication)
|
||||
|
||||
string(TOLOWER ${CMAKE_BUILD_TYPE} lower_build_type)
|
||||
|
||||
@@ -33,13 +37,11 @@ set(mg_single_node_v2_sources
|
||||
memgraph.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 mg-audit)
|
||||
|
||||
# memgraph main executable
|
||||
add_executable(memgraph ${mg_single_node_v2_sources})
|
||||
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-communication-metrics mg-memory mg-utils mg-license mg-settings mg-glue mg-flags)
|
||||
|
||||
# NOTE: `include/mg_procedure.syms` describes a pattern match for symbols which
|
||||
# should be dynamically exported, so that `dlopen` can correctly link the
|
||||
@@ -72,7 +74,7 @@ if(lower_build_type STREQUAL "release")
|
||||
COMMENT "Stripping symbols and sections from memgraph")
|
||||
endif()
|
||||
|
||||
# Generate the configuration file.
|
||||
# Generate the configuration file under the build directory.
|
||||
add_custom_command(TARGET memgraph POST_BUILD
|
||||
COMMAND ${CMAKE_SOURCE_DIR}/config/generate.py
|
||||
${CMAKE_BINARY_DIR}/memgraph
|
||||
@@ -81,6 +83,11 @@ add_custom_command(TARGET memgraph POST_BUILD
|
||||
${CMAKE_SOURCE_DIR}/config/flags.yaml
|
||||
BYPRODUCTS ${CMAKE_BINARY_DIR}/config/memgraph.conf
|
||||
COMMENT "Generating memgraph configuration file")
|
||||
# Copy the mappings file to the build directory.
|
||||
add_custom_command(TARGET memgraph POST_BUILD
|
||||
COMMAND ${CMAKE_COMMAND} -E copy
|
||||
${CMAKE_SOURCE_DIR}/config/mappings.json
|
||||
${CMAKE_BINARY_DIR}/config/apoc_compatibility_mappings.json)
|
||||
|
||||
# Everything here is under "memgraph" install component.
|
||||
set(CMAKE_INSTALL_DEFAULT_COMPONENT_NAME "memgraph")
|
||||
@@ -116,6 +123,9 @@ install(FILES ${CMAKE_SOURCE_DIR}/include/mgp.hpp
|
||||
# Install the config file (must use absolute path).
|
||||
install(FILES ${CMAKE_BINARY_DIR}/config/memgraph.conf
|
||||
DESTINATION /etc/memgraph RENAME memgraph.conf)
|
||||
# Install the mappings file (must use absolute path).
|
||||
install(FILES ${CMAKE_BINARY_DIR}/config/apoc_compatibility_mappings.json
|
||||
DESTINATION /etc/memgraph RENAME apoc_compatibility_mappings.json)
|
||||
|
||||
# Install logrotate configuration (must use absolute path).
|
||||
install(FILES ${CMAKE_SOURCE_DIR}/release/logrotate.conf
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
// Copyright 2022 Memgraph Ltd.
|
||||
// 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
|
||||
@@ -21,5 +21,6 @@ namespace memgraph::auth {
|
||||
class AuthException : public utils::BasicException {
|
||||
public:
|
||||
using utils::BasicException::BasicException;
|
||||
SPECIALIZE_GET_EXCEPTION_NAME(AuthException)
|
||||
};
|
||||
} // namespace memgraph::auth
|
||||
|
||||
@@ -16,9 +16,13 @@ set(communication_src_files
|
||||
|
||||
find_package(Boost REQUIRED)
|
||||
|
||||
add_library(mg-communication-metrics STATIC metrics.cpp)
|
||||
target_link_libraries(mg-communication-metrics json)
|
||||
|
||||
add_library(mg-communication STATIC ${communication_src_files})
|
||||
target_link_libraries(mg-communication Boost::headers Threads::Threads mg-utils mg-io mg-auth fmt::fmt gflags)
|
||||
target_link_libraries(mg-communication Boost::headers Threads::Threads mg-utils mg-io mg-auth fmt::fmt gflags mg-communication-metrics mg-events)
|
||||
|
||||
find_package(OpenSSL REQUIRED)
|
||||
target_link_libraries(mg-communication ${OPENSSL_LIBRARIES})
|
||||
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
|
||||
// included in the file licenses/BSL.txt; by using this file, you agree to be bound by the terms of the Business Source
|
||||
@@ -264,4 +264,5 @@ bool Client::ReadMessageData(Marker marker, Value &ret) {
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
} // 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
|
||||
// included in the file licenses/BSL.txt; by using this file, you agree to be bound by the terms of the Business Source
|
||||
@@ -38,6 +38,7 @@ class FailureResponseException : public utils::BasicException {
|
||||
: utils::BasicException{message}, code_{code} {}
|
||||
|
||||
const std::string &code() const { return code_; }
|
||||
SPECIALIZE_GET_EXCEPTION_NAME(FailureResponseException)
|
||||
|
||||
private:
|
||||
std::string code_;
|
||||
@@ -49,6 +50,7 @@ class FailureResponseException : public utils::BasicException {
|
||||
class ClientQueryException : public FailureResponseException {
|
||||
public:
|
||||
using FailureResponseException::FailureResponseException;
|
||||
SPECIALIZE_GET_EXCEPTION_NAME(ClientQueryException)
|
||||
};
|
||||
|
||||
/// This exception is thrown whenever a fatal error occurs during query
|
||||
@@ -57,6 +59,7 @@ class ClientQueryException : public FailureResponseException {
|
||||
class ClientFatalException : public utils::BasicException {
|
||||
public:
|
||||
using utils::BasicException::BasicException;
|
||||
SPECIALIZE_GET_EXCEPTION_NAME(ClientFatalException)
|
||||
};
|
||||
|
||||
// Internal exception used whenever a communication error occurs. You should
|
||||
@@ -64,6 +67,7 @@ class ClientFatalException : public utils::BasicException {
|
||||
class ServerCommunicationException : public ClientFatalException {
|
||||
public:
|
||||
ServerCommunicationException() : ClientFatalException("Couldn't communicate with the server!") {}
|
||||
SPECIALIZE_GET_EXCEPTION_NAME(ServerCommunicationException)
|
||||
};
|
||||
|
||||
// Internal exception used whenever a malformed data error occurs. You should
|
||||
@@ -71,6 +75,7 @@ class ServerCommunicationException : public ClientFatalException {
|
||||
class ServerMalformedDataException : public ClientFatalException {
|
||||
public:
|
||||
ServerMalformedDataException() : ClientFatalException("The server sent malformed data!") {}
|
||||
SPECIALIZE_GET_EXCEPTION_NAME(ServerMalformedDataException)
|
||||
};
|
||||
|
||||
/// Structure that is used to return results from an executed query.
|
||||
@@ -155,4 +160,5 @@ class Client final {
|
||||
ChunkedEncoderBuffer<communication::ClientOutputStream> encoder_buffer_{output_stream_};
|
||||
ClientEncoder encoder_{encoder_buffer_};
|
||||
};
|
||||
|
||||
} // namespace memgraph::communication::bolt
|
||||
|
||||
55
src/communication/bolt/metrics.hpp
Normal file
55
src/communication/bolt/metrics.hpp
Normal file
@@ -0,0 +1,55 @@
|
||||
// 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 "communication/bolt/v1/value.hpp"
|
||||
#include "communication/metrics.hpp"
|
||||
|
||||
namespace memgraph::communication::bolt {
|
||||
|
||||
template <typename TSession>
|
||||
inline void RegisterNewSession(TSession &session, Value &metadata) {
|
||||
auto &data = metadata.ValueMap();
|
||||
session.metrics_ = bolt_metrics.Add(data.contains("user_agent") ? data["user_agent"].ValueString() : "unknown",
|
||||
fmt::format("{}.{}", session.version_.major, session.version_.minor),
|
||||
session.client_supported_bolt_versions_);
|
||||
++session.metrics_.value()->sessions;
|
||||
auto conn_type = (!data.contains("scheme") || data["scheme"].ValueString() == "none")
|
||||
? BoltMetrics::ConnectionType::kAnonymous
|
||||
: BoltMetrics::ConnectionType::kBasic;
|
||||
++session.metrics_.value()->connection_types[(int)conn_type];
|
||||
}
|
||||
|
||||
template <typename TSession>
|
||||
inline void TouchNewSession(TSession &session, Value &metadata) {
|
||||
auto &data = metadata.ValueMap();
|
||||
session.metrics_ = bolt_metrics.Add(data.contains("user_agent") ? data["user_agent"].ValueString() : "unknown");
|
||||
}
|
||||
|
||||
template <typename TSession>
|
||||
inline void UpdateNewSession(TSession &session, Value &metadata) {
|
||||
auto &data = metadata.ValueMap();
|
||||
session.metrics_.value()->bolt_v = fmt::format("{}.{}", session.version_.major, session.version_.minor);
|
||||
session.metrics_.value()->supported_bolt_v = session.client_supported_bolt_versions_;
|
||||
++session.metrics_.value()->sessions;
|
||||
auto conn_type = (!data.contains("scheme") || data["scheme"].ValueString() == "none")
|
||||
? BoltMetrics::ConnectionType::kAnonymous
|
||||
: BoltMetrics::ConnectionType::kBasic;
|
||||
++session.metrics_.value()->connection_types[(int)conn_type];
|
||||
}
|
||||
|
||||
template <typename TSession>
|
||||
inline void IncrementQueryMetrics(TSession &session) {
|
||||
++session.metrics_.value()->queries;
|
||||
}
|
||||
|
||||
} // 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
|
||||
// included in the file licenses/BSL.txt; by using this file, you agree to be bound by the terms of the Business Source
|
||||
@@ -30,6 +30,7 @@ namespace memgraph::communication::bolt {
|
||||
class ClientError : public utils::BasicException {
|
||||
public:
|
||||
using utils::BasicException::BasicException;
|
||||
SPECIALIZE_GET_EXCEPTION_NAME(ClientError)
|
||||
};
|
||||
|
||||
/**
|
||||
@@ -67,6 +68,7 @@ class VerboseError : public utils::BasicException {
|
||||
code_(fmt::format("Memgraph.{}.{}.{}", ClassificationToString(classification), category, title)) {}
|
||||
|
||||
const std::string &code() const noexcept { return code_; }
|
||||
SPECIALIZE_GET_EXCEPTION_NAME(VerboseError)
|
||||
|
||||
private:
|
||||
std::string ClassificationToString(Classification classification) {
|
||||
|
||||
@@ -27,6 +27,7 @@
|
||||
#include "communication/bolt/v1/states/handshake.hpp"
|
||||
#include "communication/bolt/v1/states/init.hpp"
|
||||
#include "communication/bolt/v1/value.hpp"
|
||||
#include "communication/metrics.hpp"
|
||||
#include "dbms/constants.hpp"
|
||||
#include "dbms/global.hpp"
|
||||
#include "utils/exceptions.hpp"
|
||||
@@ -43,6 +44,7 @@ namespace memgraph::communication::bolt {
|
||||
class SessionException : public utils::BasicException {
|
||||
public:
|
||||
using utils::BasicException::BasicException;
|
||||
SPECIALIZE_GET_EXCEPTION_NAME(SessionException)
|
||||
};
|
||||
|
||||
/**
|
||||
@@ -54,7 +56,7 @@ class SessionException : public utils::BasicException {
|
||||
* @tparam TOutputStream type of output stream that will be used
|
||||
*/
|
||||
template <typename TInputStream, typename TOutputStream>
|
||||
class Session : public dbms::SessionInterface {
|
||||
class Session {
|
||||
public:
|
||||
using TEncoder = Encoder<ChunkedEncoderBuffer<TOutputStream>>;
|
||||
|
||||
@@ -159,6 +161,7 @@ class Session : public dbms::SessionInterface {
|
||||
break;
|
||||
case State::Idle:
|
||||
case State::Result:
|
||||
at_least_one_run_ = true;
|
||||
state_ = StateExecutingRun(*this, state_);
|
||||
break;
|
||||
case State::Error:
|
||||
@@ -180,6 +183,12 @@ class Session : public dbms::SessionInterface {
|
||||
}
|
||||
}
|
||||
|
||||
void HandleError() {
|
||||
if (!at_least_one_run_) {
|
||||
spdlog::info("Sudden connection loss. Make sure the client supports Memgraph.");
|
||||
}
|
||||
}
|
||||
|
||||
// TODO: Rethink if there is a way to hide some members. At the momement all of them are public.
|
||||
TInputStream &input_stream_;
|
||||
TOutputStream &output_stream_;
|
||||
@@ -192,6 +201,7 @@ class Session : public dbms::SessionInterface {
|
||||
|
||||
bool handshake_done_{false};
|
||||
State state_{State::Handshake};
|
||||
bool at_least_one_run_{false};
|
||||
|
||||
struct Version {
|
||||
uint8_t major;
|
||||
@@ -199,9 +209,11 @@ class Session : public dbms::SessionInterface {
|
||||
};
|
||||
|
||||
Version version_;
|
||||
std::vector<std::string> client_supported_bolt_versions_;
|
||||
std::optional<BoltMetrics::Metrics> metrics_;
|
||||
|
||||
std::string GetDatabaseName() const override = 0;
|
||||
std::string UUID() const final { return session_uuid_; }
|
||||
virtual std::string GetCurrentDB() const = 0;
|
||||
std::string UUID() const { return session_uuid_; }
|
||||
|
||||
private:
|
||||
void ClientFailureInvalidData() {
|
||||
|
||||
@@ -18,6 +18,7 @@
|
||||
#include <string_view>
|
||||
#include <vector>
|
||||
|
||||
#include "communication/bolt/metrics.hpp"
|
||||
#include "communication/bolt/v1/codes.hpp"
|
||||
#include "communication/bolt/v1/constants.hpp"
|
||||
#include "communication/bolt/v1/exceptions.hpp"
|
||||
@@ -208,7 +209,10 @@ 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");
|
||||
|
||||
spdlog::debug("[Run - {}] '{}'", session.GetDatabaseName(), query.ValueString());
|
||||
spdlog::debug("[Run - {}] '{}'", session.GetCurrentDB(), query.ValueString());
|
||||
|
||||
// Increment number of queries in the metrics
|
||||
IncrementQueryMetrics(session);
|
||||
|
||||
try {
|
||||
// Interpret can throw.
|
||||
@@ -272,7 +276,10 @@ State HandleRunV4(TSession &session, const State state, const Marker marker) {
|
||||
return HandleFailure(session, e);
|
||||
}
|
||||
|
||||
spdlog::debug("[Run - {}] '{}'", session.GetDatabaseName(), query.ValueString());
|
||||
spdlog::debug("[Run - {}] '{}'", session.GetCurrentDB(), query.ValueString());
|
||||
|
||||
// Increment number of queries in the metrics
|
||||
IncrementQueryMetrics(session);
|
||||
|
||||
try {
|
||||
// Interpret can throw.
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
// Copyright 2022 Memgraph Ltd.
|
||||
// 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
|
||||
@@ -24,6 +24,31 @@
|
||||
|
||||
namespace memgraph::communication::bolt {
|
||||
|
||||
inline std::vector<std::string> StringifySupportedVersions(uint8_t *data) {
|
||||
std::vector<std::string> res;
|
||||
uint8_t range_i = 1;
|
||||
uint8_t minor_i = 2;
|
||||
uint8_t major_i = 3;
|
||||
uint8_t chunk_size = 4;
|
||||
uint8_t n_chunks = 4;
|
||||
auto stringify_version = [](uint8_t major, uint8_t minor) { return fmt::format("{}.{}", major, minor); };
|
||||
for (uint8_t i = 0; i < n_chunks; ++i) {
|
||||
const uint32_t full_version = *((uint32_t *)data);
|
||||
if (full_version == 0) break;
|
||||
if (data[1] != 0) { // Supports a range of versions
|
||||
uint8_t range = data[range_i];
|
||||
auto max_minor = data[minor_i];
|
||||
for (uint8_t r = 0; r <= range; ++r) {
|
||||
res.push_back(stringify_version(data[major_i], max_minor - r));
|
||||
}
|
||||
} else {
|
||||
res.push_back(stringify_version(data[major_i], data[minor_i]));
|
||||
}
|
||||
data += chunk_size;
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
inline bool CopyProtocolInformationIfSupported(uint16_t version, uint8_t *protocol) {
|
||||
const auto *supported_version = std::find(std::begin(kSupportedVersions), std::end(kSupportedVersions), version);
|
||||
if (supported_version != std::end(kSupportedVersions)) {
|
||||
@@ -71,6 +96,8 @@ State StateHandshakeRun(TSession &session) {
|
||||
auto dataPosition = session.input_stream_.data() + sizeof(kPreamble);
|
||||
uint8_t protocol[4] = {0x00};
|
||||
|
||||
session.client_supported_bolt_versions_ = std::move(StringifySupportedVersions(dataPosition));
|
||||
|
||||
for (int i = 0; i < 4 && !protocol[3]; ++i) {
|
||||
// If there is an offset defined (e.g. 0x00 0x03 0x03 0x04) the second byte
|
||||
// That would enable the client to pick between 4.0 and 4.3 versions
|
||||
|
||||
@@ -11,6 +11,7 @@
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <fmt/core.h>
|
||||
#include <fmt/format.h>
|
||||
#include <optional>
|
||||
|
||||
@@ -18,6 +19,7 @@
|
||||
#include "communication/bolt/v1/state.hpp"
|
||||
#include "communication/bolt/v1/value.hpp"
|
||||
#include "communication/exceptions.hpp"
|
||||
#include "communication/metrics.hpp"
|
||||
#include "spdlog/spdlog.h"
|
||||
#include "utils/likely.hpp"
|
||||
#include "utils/logging.hpp"
|
||||
@@ -174,7 +176,7 @@ State SendSuccessMessage(TSession &session) {
|
||||
// we send a hardcoded value for now.
|
||||
std::map<std::string, Value> metadata{{"connection_id", "bolt-1"}};
|
||||
if (auto server_name = session.GetServerNameForInit(); server_name) {
|
||||
metadata.insert({"server", *server_name});
|
||||
metadata.insert({"server", std::move(*server_name)});
|
||||
}
|
||||
bool success_sent = session.encoder_.MessageSuccess(metadata);
|
||||
if (!success_sent) {
|
||||
@@ -201,6 +203,9 @@ State StateInitRunV1(TSession &session, const Marker marker, const Signature sig
|
||||
return result.value();
|
||||
}
|
||||
|
||||
// Register session to metrics
|
||||
RegisterNewSession(session, *maybeMetadata);
|
||||
|
||||
return SendSuccessMessage(session);
|
||||
}
|
||||
|
||||
@@ -227,6 +232,9 @@ State StateInitRunV4(TSession &session, Marker marker, Signature signature) {
|
||||
return result.value();
|
||||
}
|
||||
|
||||
// Register session to metrics
|
||||
RegisterNewSession(session, *maybeMetadata);
|
||||
|
||||
return SendSuccessMessage(session);
|
||||
}
|
||||
|
||||
@@ -247,6 +255,10 @@ State StateInitRunV5(TSession &session, Marker marker, Signature signature) {
|
||||
if (SendSuccessMessage(session) == State::Close) {
|
||||
return State::Close;
|
||||
}
|
||||
|
||||
// Register session to metrics
|
||||
TouchNewSession(session, *maybeMetadata);
|
||||
|
||||
// Stay in Init
|
||||
return State::Init;
|
||||
}
|
||||
@@ -274,6 +286,10 @@ State StateInitRunV5(TSession &session, Marker marker, Signature signature) {
|
||||
if (SendSuccessMessage(session) == State::Close) {
|
||||
return State::Close;
|
||||
}
|
||||
|
||||
// Register session to metrics
|
||||
UpdateNewSession(session, *maybeMetadata);
|
||||
|
||||
return State::Idle;
|
||||
}
|
||||
|
||||
|
||||
@@ -276,6 +276,7 @@ class ValueException : public utils::BasicException {
|
||||
public:
|
||||
using utils::BasicException::BasicException;
|
||||
ValueException() : BasicException("Incompatible template param and type!") {}
|
||||
SPECIALIZE_GET_EXCEPTION_NAME(ValueException)
|
||||
};
|
||||
|
||||
/**
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
// Copyright 2022 Memgraph Ltd.
|
||||
// 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
|
||||
@@ -43,6 +43,7 @@ class Buffer final {
|
||||
Buffer(Buffer &&) = delete;
|
||||
Buffer &operator=(const Buffer &) = delete;
|
||||
Buffer &operator=(Buffer &&) = delete;
|
||||
~Buffer() = default;
|
||||
|
||||
/**
|
||||
* This class provides all functions from the buffer that are needed to allow
|
||||
@@ -50,12 +51,13 @@ class Buffer final {
|
||||
*/
|
||||
class ReadEnd {
|
||||
public:
|
||||
ReadEnd(Buffer *buffer);
|
||||
explicit ReadEnd(Buffer *buffer);
|
||||
|
||||
ReadEnd(const ReadEnd &) = delete;
|
||||
ReadEnd(ReadEnd &&) = delete;
|
||||
ReadEnd &operator=(const ReadEnd &) = delete;
|
||||
ReadEnd &operator=(ReadEnd &&) = delete;
|
||||
~ReadEnd() = default;
|
||||
|
||||
uint8_t *data();
|
||||
|
||||
@@ -77,12 +79,13 @@ class Buffer final {
|
||||
*/
|
||||
class WriteEnd {
|
||||
public:
|
||||
WriteEnd(Buffer *buffer);
|
||||
explicit WriteEnd(Buffer *buffer);
|
||||
|
||||
WriteEnd(const WriteEnd &) = delete;
|
||||
WriteEnd(WriteEnd &&) = delete;
|
||||
WriteEnd &operator=(const WriteEnd &) = delete;
|
||||
WriteEnd &operator=(WriteEnd &&) = delete;
|
||||
~WriteEnd() = default;
|
||||
|
||||
io::network::StreamBuffer Allocate();
|
||||
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
// Copyright 2022 Memgraph Ltd.
|
||||
// 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
|
||||
@@ -15,6 +15,10 @@
|
||||
#include <openssl/err.h>
|
||||
#include <openssl/ssl.h>
|
||||
|
||||
// Centos 7 OpenSSL includes libkrb5 which has brings in macros TRUE and FALSE. undef to prevent issues.
|
||||
#undef TRUE
|
||||
#undef FALSE
|
||||
|
||||
#include "communication/buffer.hpp"
|
||||
#include "communication/context.hpp"
|
||||
#include "communication/init.hpp"
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
// Copyright 2022 Memgraph Ltd.
|
||||
// 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
|
||||
@@ -17,6 +17,10 @@
|
||||
#include <openssl/ssl.h>
|
||||
#include <boost/asio/ssl/context.hpp>
|
||||
|
||||
// Centos 7 OpenSSL includes libkrb5 which has brings in macros TRUE and FALSE. undef to prevent issues.
|
||||
#undef TRUE
|
||||
#undef FALSE
|
||||
|
||||
namespace memgraph::communication {
|
||||
|
||||
/**
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
// Copyright 2022 Memgraph Ltd.
|
||||
// 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
|
||||
@@ -21,5 +21,6 @@ namespace memgraph::communication {
|
||||
*/
|
||||
class SessionClosedException : public utils::BasicException {
|
||||
using utils::BasicException::BasicException;
|
||||
SPECIALIZE_GET_EXCEPTION_NAME(SessionClosedException)
|
||||
};
|
||||
} // namespace memgraph::communication
|
||||
|
||||
@@ -26,10 +26,7 @@ class Server final {
|
||||
using tcp = boost::asio::ip::tcp;
|
||||
|
||||
public:
|
||||
explicit 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})} {}
|
||||
explicit Server(io::network::Endpoint endpoint, TSessionContext *session_context, ServerContext *context);
|
||||
|
||||
Server(const Server &) = delete;
|
||||
Server(Server &&) = delete;
|
||||
@@ -41,11 +38,7 @@ class Server final {
|
||||
"Server wasn't shutdown properly");
|
||||
}
|
||||
|
||||
void Start() {
|
||||
MG_ASSERT(!background_thread_, "The server was already started!");
|
||||
listener_->Run();
|
||||
background_thread_.emplace([this] { ioc_.run(); });
|
||||
}
|
||||
void Start();
|
||||
|
||||
void Shutdown() { ioc_.stop(); }
|
||||
|
||||
@@ -55,7 +48,7 @@ class Server final {
|
||||
}
|
||||
}
|
||||
bool IsRunning() const { return background_thread_ && !ioc_.stopped(); }
|
||||
tcp::endpoint GetEndpoint() const { return listener_->GetEndpoint(); }
|
||||
tcp::endpoint GetEndpoint() const;
|
||||
|
||||
private:
|
||||
boost::asio::io_context ioc_;
|
||||
@@ -63,4 +56,22 @@ class Server final {
|
||||
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
|
||||
|
||||
42
src/communication/metrics.cpp
Normal file
42
src/communication/metrics.cpp
Normal file
@@ -0,0 +1,42 @@
|
||||
// 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.
|
||||
|
||||
#include "metrics.hpp"
|
||||
|
||||
namespace {
|
||||
constexpr auto kName = "name";
|
||||
constexpr auto kSupportedBoltVersions = "supported_bolt_versions";
|
||||
constexpr auto kBoltVersion = "bolt_version";
|
||||
constexpr auto kConnectionTypes = "connection_types";
|
||||
constexpr auto kSessions = "sessions";
|
||||
constexpr auto kQueries = "queries";
|
||||
} // namespace
|
||||
namespace memgraph::communication {
|
||||
|
||||
// NOLINTNEXTLINE(cppcoreguidelines-avoid-non-const-global-variables)
|
||||
BoltMetrics bolt_metrics;
|
||||
|
||||
nlohmann::json BoltMetrics::Info::ToJson() const {
|
||||
nlohmann::json res;
|
||||
|
||||
res[kName] = name;
|
||||
res[kSupportedBoltVersions] = nlohmann::json::array();
|
||||
for (const auto &sbv : supported_bolt_v) {
|
||||
res[kSupportedBoltVersions].push_back(sbv);
|
||||
}
|
||||
res[kBoltVersion] = bolt_v;
|
||||
res[kConnectionTypes] = {{ConnectionTypeStr((ConnectionType)0), connection_types[0].load()},
|
||||
{ConnectionTypeStr((ConnectionType)1), connection_types[1].load()}};
|
||||
res[kSessions] = sessions.load();
|
||||
res[kQueries] = queries.load();
|
||||
return res;
|
||||
}
|
||||
} // namespace memgraph::communication
|
||||
116
src/communication/metrics.hpp
Normal file
116
src/communication/metrics.hpp
Normal file
@@ -0,0 +1,116 @@
|
||||
// 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 <atomic>
|
||||
#include <map>
|
||||
#include <mutex>
|
||||
#include <shared_mutex>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
#include <json/json.hpp>
|
||||
|
||||
namespace memgraph::communication {
|
||||
|
||||
class BoltMetrics {
|
||||
public:
|
||||
enum class ConnectionType { kAnonymous = 0, kBasic, Count };
|
||||
static constexpr std::array<std::string_view, (int)ConnectionType::Count> ct_to_str = {"anonymous", "basic"};
|
||||
static std::string ConnectionTypeStr(ConnectionType type) { return std::string(ct_to_str[(int)type]); }
|
||||
class Metrics;
|
||||
|
||||
struct Info {
|
||||
explicit Info(std::string name) : name(std::move(name)) {}
|
||||
Info(std::string name, std::string bolt_v, std::vector<std::string> supported_bolt_v)
|
||||
: name(std::move(name)), bolt_v(std::move(bolt_v)), supported_bolt_v(std::move(supported_bolt_v)) {}
|
||||
|
||||
const std::string name; //!< Driver name
|
||||
std::string bolt_v; //!< Bolt version used
|
||||
std::vector<std::string> supported_bolt_v; //!< Bolt versions supported by the driver
|
||||
std::atomic_int connection_types[(int)ConnectionType::Count]; //!< Authentication used when connecting
|
||||
std::atomic_int sessions; //!< Number of sessions using the same driver
|
||||
std::atomic_int queries; //!< Queries executed by the driver
|
||||
|
||||
nlohmann::json ToJson() const;
|
||||
|
||||
private:
|
||||
friend class Metrics;
|
||||
std::atomic_int concurrent_users;
|
||||
};
|
||||
|
||||
class Metrics {
|
||||
friend class BoltMetrics;
|
||||
explicit Metrics(Info &info) : info_(&info) { ++info_->concurrent_users; }
|
||||
|
||||
public:
|
||||
~Metrics() {
|
||||
if (info_) --info_->concurrent_users;
|
||||
}
|
||||
|
||||
Metrics(const Metrics &other) : info_(other.info_) { ++info_->concurrent_users; }
|
||||
Metrics(Metrics &&other) noexcept : info_(other.info_) { other.info_ = nullptr; }
|
||||
Metrics &operator=(const Metrics &other) {
|
||||
if (this != &other) {
|
||||
if (info_) --info_->concurrent_users;
|
||||
info_ = other.info_;
|
||||
if (info_) ++info_->concurrent_users;
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
Metrics &operator=(Metrics &&other) noexcept {
|
||||
if (this != &other) {
|
||||
if (info_) --info_->concurrent_users;
|
||||
info_ = other.info_;
|
||||
other.info_ = nullptr; // Invalidate the source object
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
|
||||
Info *operator->() { return info_; }
|
||||
|
||||
Info *info_;
|
||||
};
|
||||
|
||||
Metrics Add(std::string name) {
|
||||
std::unique_lock<std::mutex> l(mtx);
|
||||
auto key = name;
|
||||
auto [it, _] = info.emplace(std::piecewise_construct, std::forward_as_tuple(std::move(key)),
|
||||
std::forward_as_tuple(std::move(name)));
|
||||
return Metrics(it->second);
|
||||
}
|
||||
|
||||
Metrics Add(std::string name, std::string bolt_v, std::vector<std::string> supported_bolt_v) {
|
||||
std::unique_lock<std::mutex> l(mtx);
|
||||
auto key = name;
|
||||
auto [it, _] = info.emplace(std::piecewise_construct, std::forward_as_tuple(std::move(key)),
|
||||
std::forward_as_tuple(std::move(name), std::move(bolt_v), std::move(supported_bolt_v)));
|
||||
return Metrics(it->second);
|
||||
}
|
||||
|
||||
nlohmann::json ToJson() {
|
||||
std::unique_lock<std::mutex> l(mtx);
|
||||
auto res = nlohmann::json::array();
|
||||
for (const auto &[_, client_info] : info) {
|
||||
res.push_back(client_info.ToJson());
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
private:
|
||||
mutable std::mutex mtx;
|
||||
std::map<std::string, Info> info;
|
||||
};
|
||||
|
||||
extern BoltMetrics bolt_metrics;
|
||||
|
||||
} // namespace memgraph::communication
|
||||
@@ -58,11 +58,11 @@ class Server final {
|
||||
* Constructs and binds server to endpoint, operates on session data and
|
||||
* invokes workers_count workers
|
||||
*/
|
||||
Server(const io::network::Endpoint &endpoint, TSessionContext *session_context, ServerContext *context,
|
||||
Server(io::network::Endpoint endpoint, TSessionContext *session_context, ServerContext *context,
|
||||
int inactivity_timeout_sec, const std::string &service_name,
|
||||
size_t workers_count = std::thread::hardware_concurrency())
|
||||
: alive_(false),
|
||||
endpoint_(endpoint),
|
||||
endpoint_(std::move(endpoint)),
|
||||
listener_(session_context, context, inactivity_timeout_sec, service_name, workers_count),
|
||||
service_name_(service_name) {}
|
||||
|
||||
|
||||
@@ -22,6 +22,10 @@
|
||||
#include <openssl/err.h>
|
||||
#include <openssl/ssl.h>
|
||||
|
||||
// Centos 7 OpenSSL includes libkrb5 which has brings in macros TRUE and FALSE. undef to prevent issues.
|
||||
#undef TRUE
|
||||
#undef FALSE
|
||||
|
||||
#include "communication/buffer.hpp"
|
||||
#include "communication/context.hpp"
|
||||
#include "communication/exceptions.hpp"
|
||||
|
||||
@@ -73,40 +73,19 @@ class Server final {
|
||||
* invokes workers_count workers
|
||||
*/
|
||||
Server(ServerEndpoint &endpoint, TSessionContext *session_context, ServerContext *server_context,
|
||||
const int inactivity_timeout_sec, const std::string_view service_name,
|
||||
size_t workers_count = std::thread::hardware_concurrency())
|
||||
: 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)} {}
|
||||
int inactivity_timeout_sec, std::string_view service_name,
|
||||
size_t workers_count = std::thread::hardware_concurrency());
|
||||
|
||||
~Server() { MG_ASSERT(!IsRunning(), "Server wasn't shutdown properly"); }
|
||||
~Server();
|
||||
|
||||
Server(const Server &) = delete;
|
||||
Server(Server &&) = delete;
|
||||
Server &operator=(const Server &) = delete;
|
||||
Server &operator=(Server &&) = delete;
|
||||
|
||||
const auto &Endpoint() const {
|
||||
MG_ASSERT(IsRunning(), "You can't get the server endpoint when it's not running!");
|
||||
return endpoint_;
|
||||
}
|
||||
const auto &Endpoint() const;
|
||||
|
||||
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;
|
||||
}
|
||||
bool Start();
|
||||
|
||||
void Shutdown() {
|
||||
context_thread_pool_.Shutdown();
|
||||
@@ -115,7 +94,7 @@ class Server final {
|
||||
|
||||
void AwaitShutdown() { context_thread_pool_.AwaitShutdown(); }
|
||||
|
||||
bool IsRunning() const noexcept { return context_thread_pool_.IsRunning() && listener_->IsRunning(); }
|
||||
bool IsRunning() const noexcept;
|
||||
|
||||
private:
|
||||
ServerEndpoint endpoint_;
|
||||
@@ -125,4 +104,46 @@ class Server final {
|
||||
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
|
||||
|
||||
@@ -110,11 +110,7 @@ class WebsocketSession : public std::enable_shared_from_this<WebsocketSession<TS
|
||||
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;
|
||||
@@ -171,14 +167,15 @@ class WebsocketSession : public std::enable_shared_from_this<WebsocketSession<TS
|
||||
: ws_(std::move(socket)),
|
||||
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); }),
|
||||
session_{*session_context, endpoint, input_buffer_.read_end(), &output_stream_},
|
||||
session_{session_context->ic, endpoint, input_buffer_.read_end(), &output_stream_, session_context->auth,
|
||||
#ifdef MG_ENTERPRISE
|
||||
session_context->audit_log
|
||||
#endif
|
||||
},
|
||||
session_context_{session_context},
|
||||
endpoint_{endpoint},
|
||||
remote_endpoint_{ws_.next_layer().socket().remote_endpoint()},
|
||||
service_name_{service_name} {
|
||||
#ifdef MG_ENTERPRISE
|
||||
session_context_->Register(session_);
|
||||
#endif
|
||||
}
|
||||
|
||||
void OnAccept(boost::beast::error_code ec) {
|
||||
@@ -286,11 +283,7 @@ class Session final : public std::enable_shared_from_this<Session<TSession, TSes
|
||||
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(Session &&) = delete;
|
||||
@@ -366,17 +359,17 @@ class Session final : public std::enable_shared_from_this<Session<TSession, TSes
|
||||
: socket_(CreateSocket(std::move(socket), server_context)),
|
||||
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); }),
|
||||
session_{*session_context, endpoint, input_buffer_.read_end(), &output_stream_},
|
||||
session_{session_context->ic, endpoint, input_buffer_.read_end(), &output_stream_, session_context->auth,
|
||||
#ifdef MG_ENTERPRISE
|
||||
session_context->audit_log
|
||||
#endif
|
||||
},
|
||||
session_context_{session_context},
|
||||
endpoint_{endpoint},
|
||||
remote_endpoint_{GetRemoteEndpoint()},
|
||||
service_name_{service_name},
|
||||
timeout_seconds_(inactivity_timeout_sec),
|
||||
timeout_timer_(GetExecutor()) {
|
||||
#ifdef MG_ENTERPRISE
|
||||
// TODO Try to remove Register (see comment at SessionInterface declaration)
|
||||
session_context_->Register(session_);
|
||||
#endif
|
||||
ExecuteForSocket([](auto &&socket) {
|
||||
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
|
||||
@@ -413,6 +406,8 @@ class Session final : public std::enable_shared_from_this<Session<TSession, TSes
|
||||
|
||||
void OnRead(const boost::system::error_code &ec, const size_t bytes_transferred) {
|
||||
if (ec) {
|
||||
// TODO Check if client disconnected
|
||||
session_.HandleError();
|
||||
return OnError(ec);
|
||||
}
|
||||
input_buffer_.write_end()->Written(bytes_transferred);
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
// Copyright 2022 Memgraph Ltd.
|
||||
// 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
|
||||
@@ -175,6 +175,11 @@ void Session::OnRead(const boost::beast::error_code ec, const size_t /*bytes_tra
|
||||
return;
|
||||
}
|
||||
|
||||
if (ec) {
|
||||
LogError(ec, "read");
|
||||
return;
|
||||
}
|
||||
|
||||
if (!IsAuthenticated()) {
|
||||
auto response = nlohmann::json();
|
||||
auto auth_failed = [this, &response](const std::string &message) {
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
// Copyright 2022 Memgraph Ltd.
|
||||
// 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
|
||||
|
||||
@@ -35,6 +35,7 @@ namespace memgraph::csv {
|
||||
|
||||
class CsvReadException : public utils::BasicException {
|
||||
using utils::BasicException::BasicException;
|
||||
SPECIALIZE_GET_EXCEPTION_NAME(CsvReadException)
|
||||
};
|
||||
|
||||
class FileCsvSource {
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
// Copyright 2022 Memgraph Ltd.
|
||||
// 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
|
||||
@@ -31,7 +31,7 @@
|
||||
template <typename TElement>
|
||||
class RingBuffer {
|
||||
public:
|
||||
explicit RingBuffer(int capacity) : capacity_(capacity) { buffer_ = std::make_unique<TElement[]>(capacity_); }
|
||||
explicit RingBuffer(int capacity) : capacity_(capacity), buffer_{std::make_unique<TElement[]>(capacity_)} {}
|
||||
|
||||
RingBuffer(const RingBuffer &) = delete;
|
||||
RingBuffer(RingBuffer &&) = delete;
|
||||
|
||||
3
src/dbms/CMakeLists.txt
Normal file
3
src/dbms/CMakeLists.txt
Normal file
@@ -0,0 +1,3 @@
|
||||
|
||||
add_library(mg-dbms STATIC database.cpp)
|
||||
target_link_libraries(mg-dbms mg-utils mg-storage-v2 mg-query)
|
||||
37
src/dbms/database.cpp
Normal file
37
src/dbms/database.cpp
Normal file
@@ -0,0 +1,37 @@
|
||||
// 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.
|
||||
|
||||
#include "dbms/database.hpp"
|
||||
#include "flags/storage_mode.hpp"
|
||||
#include "storage/v2/disk/storage.hpp"
|
||||
#include "storage/v2/inmemory/storage.hpp"
|
||||
#include "storage/v2/storage_mode.hpp"
|
||||
|
||||
template struct memgraph::utils::Gatekeeper<memgraph::dbms::Database>;
|
||||
|
||||
namespace memgraph::dbms {
|
||||
|
||||
Database::Database(const storage::Config &config)
|
||||
: trigger_store_(config.durability.storage_directory / "triggers"),
|
||||
streams_{config.durability.storage_directory / "streams"} {
|
||||
if (config.storage_mode == memgraph::storage::StorageMode::ON_DISK_TRANSACTIONAL || config.force_on_disk ||
|
||||
utils::DirExists(config.disk.main_storage_directory)) {
|
||||
storage_ = std::make_unique<storage::DiskStorage>(config);
|
||||
} else {
|
||||
storage_ = std::make_unique<storage::InMemoryStorage>(config, config.storage_mode);
|
||||
}
|
||||
}
|
||||
|
||||
void Database::SwitchToOnDisk() {
|
||||
storage_ = std::make_unique<memgraph::storage::DiskStorage>(std::move(storage_->config_));
|
||||
}
|
||||
|
||||
} // namespace memgraph::dbms
|
||||
168
src/dbms/database.hpp
Normal file
168
src/dbms/database.hpp
Normal file
@@ -0,0 +1,168 @@
|
||||
// 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 <algorithm>
|
||||
#include <filesystem>
|
||||
#include <iterator>
|
||||
#include <memory>
|
||||
#include <optional>
|
||||
#include <string_view>
|
||||
#include <unordered_map>
|
||||
|
||||
#include "query/cypher_query_interpreter.hpp"
|
||||
#include "query/stream/streams.hpp"
|
||||
#include "query/trigger.hpp"
|
||||
#include "storage/v2/storage.hpp"
|
||||
#include "utils/gatekeeper.hpp"
|
||||
|
||||
namespace memgraph::dbms {
|
||||
|
||||
struct DatabaseInfo {
|
||||
storage::StorageInfo storage_info;
|
||||
uint64_t triggers;
|
||||
uint64_t streams;
|
||||
};
|
||||
|
||||
static inline nlohmann::json ToJson(const DatabaseInfo &info) { return ToJson(info.storage_info); }
|
||||
|
||||
/**
|
||||
* @brief Class containing everything associated with a single Database
|
||||
*
|
||||
*/
|
||||
class Database {
|
||||
public:
|
||||
/**
|
||||
* @brief Construct a new Database object
|
||||
*
|
||||
* @param config storage configuration
|
||||
*/
|
||||
explicit Database(const storage::Config &config);
|
||||
|
||||
/**
|
||||
* @brief Returns the raw storage pointer.
|
||||
* @note Ideally everybody would be using an accessor
|
||||
* TODO: Remove
|
||||
*
|
||||
* @return storage::Storage*
|
||||
*/
|
||||
storage::Storage *storage() { return storage_.get(); }
|
||||
|
||||
/**
|
||||
* @brief Storage's Accessor
|
||||
*
|
||||
* @param override_isolation_level
|
||||
* @return std::unique_ptr<storage::Storage::Accessor>
|
||||
*/
|
||||
std::unique_ptr<storage::Storage::Accessor> Access(
|
||||
std::optional<storage::IsolationLevel> override_isolation_level = {}) {
|
||||
return storage_->Access(override_isolation_level);
|
||||
}
|
||||
|
||||
std::unique_ptr<storage::Storage::Accessor> UniqueAccess(
|
||||
std::optional<storage::IsolationLevel> override_isolation_level = {}) {
|
||||
return storage_->UniqueAccess(override_isolation_level);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Unique storage identified (name)
|
||||
*
|
||||
* @return const std::string&
|
||||
*/
|
||||
const std::string &id() const { return storage_->id(); }
|
||||
|
||||
/**
|
||||
* @brief Returns the storage configuration
|
||||
*
|
||||
* @return const storage::Config&
|
||||
*/
|
||||
const storage::Config &config() const { return storage_->config_; }
|
||||
|
||||
/**
|
||||
* @brief Get the storage mode
|
||||
*
|
||||
* @return storage::StorageMode
|
||||
*/
|
||||
storage::StorageMode GetStorageMode() const { return storage_->GetStorageMode(); }
|
||||
|
||||
/**
|
||||
* @brief Get the storage info
|
||||
*
|
||||
* @param force_directory Use the configured directory, do not try to decipher the multi-db version
|
||||
* @return DatabaseInfo
|
||||
*/
|
||||
DatabaseInfo GetInfo(bool force_directory = false) const {
|
||||
DatabaseInfo info;
|
||||
info.storage_info = storage_->GetInfo(force_directory);
|
||||
info.triggers = trigger_store_.GetTriggerInfo().size();
|
||||
info.streams = streams_.GetStreamInfo().size();
|
||||
return info;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Switch storage to OnDisk
|
||||
*
|
||||
*/
|
||||
void SwitchToOnDisk();
|
||||
|
||||
/**
|
||||
* @brief Returns the raw TriggerStore pointer
|
||||
*
|
||||
* @return query::TriggerStore*
|
||||
*/
|
||||
query::TriggerStore *trigger_store() { return &trigger_store_; }
|
||||
|
||||
/**
|
||||
* @brief Returns the raw Streams pointer
|
||||
*
|
||||
* @return query::stream::Streams*
|
||||
*/
|
||||
query::stream::Streams *streams() { return &streams_; }
|
||||
|
||||
/**
|
||||
* @brief Returns the raw ThreadPool pointer (used for after commit triggers)
|
||||
*
|
||||
* @return utils::ThreadPool*
|
||||
*/
|
||||
utils::ThreadPool *thread_pool() { return &after_commit_trigger_pool_; }
|
||||
|
||||
/**
|
||||
* @brief Add task to the after commit trigger thread pool
|
||||
*
|
||||
* @param new_task
|
||||
*/
|
||||
void AddTask(std::function<void()> new_task) { after_commit_trigger_pool_.AddTask(std::move(new_task)); }
|
||||
|
||||
/**
|
||||
* @brief Returns the PlanCache vector raw pointer
|
||||
*
|
||||
* @return utils::SkipList<query::PlanCacheEntry>*
|
||||
*/
|
||||
utils::SkipList<query::PlanCacheEntry> *plan_cache() { return &plan_cache_; }
|
||||
|
||||
private:
|
||||
std::unique_ptr<storage::Storage> storage_; //!< Underlying storage
|
||||
query::TriggerStore trigger_store_; //!< Triggers associated with the storage
|
||||
utils::ThreadPool after_commit_trigger_pool_{1}; //!< Thread pool for executing after commit triggers
|
||||
query::stream::Streams streams_; //!< Streams associated with the storage
|
||||
|
||||
// TODO: Move to a better place
|
||||
utils::SkipList<query::PlanCacheEntry> plan_cache_; //!< Plan cache associated with the storage
|
||||
};
|
||||
|
||||
} // namespace memgraph::dbms
|
||||
|
||||
extern template struct memgraph::utils::Gatekeeper<memgraph::dbms::Database>;
|
||||
|
||||
namespace memgraph::dbms {
|
||||
using DatabaseAccess = memgraph::utils::Gatekeeper<memgraph::dbms::Database>::Accessor;
|
||||
} // namespace memgraph::dbms
|
||||
97
src/dbms/database_handler.hpp
Normal file
97
src/dbms/database_handler.hpp
Normal file
@@ -0,0 +1,97 @@
|
||||
// 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
|
||||
|
||||
#ifdef MG_ENTERPRISE
|
||||
|
||||
#include <algorithm>
|
||||
#include <filesystem>
|
||||
#include <iterator>
|
||||
#include <memory>
|
||||
#include <optional>
|
||||
#include <string_view>
|
||||
#include <unordered_map>
|
||||
|
||||
#include "dbms/database.hpp"
|
||||
|
||||
#include "handler.hpp"
|
||||
|
||||
namespace memgraph::dbms {
|
||||
|
||||
/* NOTE
|
||||
* The Database object is shared. All the higher-level function calls should be protected.
|
||||
* Storage function calls should already be protected; add protection where needed.
|
||||
*
|
||||
* Current implementation uses a handler of Database objects. It owns them and gives
|
||||
* Gatekeeper::Accessor to it. These guarantee that the object won't be
|
||||
* destroyed unless no one is using it.
|
||||
*/
|
||||
|
||||
/**Config
|
||||
* @brief Multi-database storage handler
|
||||
*
|
||||
*/
|
||||
class DatabaseHandler : public Handler<Database> {
|
||||
public:
|
||||
using HandlerT = Handler<Database>;
|
||||
|
||||
/**
|
||||
* @brief Generate new storage associated with the passed name.
|
||||
*
|
||||
* @param name Name associating the new interpreter context
|
||||
* @param config Storage configuration
|
||||
* @return HandlerT::NewResult
|
||||
*/
|
||||
HandlerT::NewResult New(std::string_view name, storage::Config config) {
|
||||
// Control that no one is using the same data directory
|
||||
if (std::any_of(begin(), end(), [&](auto &elem) {
|
||||
auto db_acc = elem.second.access();
|
||||
MG_ASSERT(db_acc.has_value(), "Gatekeeper in invalid state");
|
||||
return db_acc->get()->config().durability.storage_directory == config.durability.storage_directory;
|
||||
})) {
|
||||
spdlog::info("Tried to generate new storage using a claimed directory.");
|
||||
return NewError::EXISTS;
|
||||
}
|
||||
config.name = name; // Set storage id via config
|
||||
return HandlerT::New(std::piecewise_construct, name, config);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief All currently active storage.
|
||||
*
|
||||
* @return std::vector<std::string>
|
||||
*/
|
||||
std::vector<std::string> All() const {
|
||||
std::vector<std::string> res;
|
||||
res.reserve(std::distance(cbegin(), cend()));
|
||||
std::for_each(cbegin(), cend(), [&](const auto &elem) { res.push_back(elem.first); });
|
||||
return res;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Get the associated storage's configuration
|
||||
*
|
||||
* @param name
|
||||
* @return std::optional<storage::Config>
|
||||
*/
|
||||
std::optional<storage::Config> GetConfig(std::string_view name) {
|
||||
auto db = Get(name);
|
||||
if (db) {
|
||||
return (*db)->config();
|
||||
}
|
||||
return std::nullopt;
|
||||
}
|
||||
};
|
||||
|
||||
} // namespace memgraph::dbms
|
||||
|
||||
#endif
|
||||
449
src/dbms/dbms_handler.hpp
Normal file
449
src/dbms/dbms_handler.hpp
Normal file
@@ -0,0 +1,449 @@
|
||||
// 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 <algorithm>
|
||||
#include <concepts>
|
||||
#include <cstdint>
|
||||
#include <filesystem>
|
||||
#include <memory>
|
||||
#include <mutex>
|
||||
#include <optional>
|
||||
#include <ostream>
|
||||
#include <stdexcept>
|
||||
#include <system_error>
|
||||
#include <unordered_map>
|
||||
|
||||
#include "auth/auth.hpp"
|
||||
#include "constants.hpp"
|
||||
#include "dbms/database.hpp"
|
||||
#include "dbms/database_handler.hpp"
|
||||
#include "global.hpp"
|
||||
#include "query/config.hpp"
|
||||
#include "query/interpreter_context.hpp"
|
||||
#include "spdlog/spdlog.h"
|
||||
#include "storage/v2/durability/durability.hpp"
|
||||
#include "storage/v2/durability/paths.hpp"
|
||||
#include "storage/v2/isolation_level.hpp"
|
||||
#include "utils/exceptions.hpp"
|
||||
#include "utils/file.hpp"
|
||||
#include "utils/logging.hpp"
|
||||
#include "utils/result.hpp"
|
||||
#include "utils/rw_lock.hpp"
|
||||
#include "utils/synchronized.hpp"
|
||||
#include "utils/uuid.hpp"
|
||||
|
||||
namespace memgraph::dbms {
|
||||
|
||||
struct Statistics {
|
||||
uint64_t num_vertex; //!< Sum of vertexes in every database
|
||||
uint64_t num_edges; //!< Sum of edges in every database
|
||||
uint64_t triggers; //!< Sum of triggers in every database
|
||||
uint64_t streams; //!< Sum of streams in every database
|
||||
uint64_t users; //!< Number of defined users
|
||||
uint64_t num_databases; //!< Number of isolated databases
|
||||
uint64_t indices; //!< Sum of indices in every database
|
||||
uint64_t constraints; //!< Sum of constraints in every database
|
||||
uint64_t storage_modes[3]; //!< Number of databases in each storage mode [IN_MEM_TX, IN_MEM_ANA, ON_DISK_TX]
|
||||
uint64_t isolation_levels[3]; //!< Number of databases in each isolation level [SNAPSHOT, READ_COMM, READ_UNC]
|
||||
uint64_t snapshot_enabled; //!< Number of databases with snapshots enabled
|
||||
uint64_t wal_enabled; //!< Number of databases with WAL enabled
|
||||
};
|
||||
|
||||
static inline nlohmann::json ToJson(const Statistics &stats) {
|
||||
nlohmann::json res;
|
||||
|
||||
res["edges"] = stats.num_edges;
|
||||
res["vertices"] = stats.num_vertex;
|
||||
res["triggers"] = stats.triggers;
|
||||
res["streams"] = stats.streams;
|
||||
res["users"] = stats.users;
|
||||
res["databases"] = stats.num_databases;
|
||||
res["indices"] = stats.indices;
|
||||
res["constraints"] = stats.constraints;
|
||||
res["storage_modes"] = {{storage::StorageModeToString((storage::StorageMode)0), stats.storage_modes[0]},
|
||||
{storage::StorageModeToString((storage::StorageMode)1), stats.storage_modes[1]},
|
||||
{storage::StorageModeToString((storage::StorageMode)2), stats.storage_modes[2]}};
|
||||
res["isolation_levels"] = {{storage::IsolationLevelToString((storage::IsolationLevel)0), stats.isolation_levels[0]},
|
||||
{storage::IsolationLevelToString((storage::IsolationLevel)1), stats.isolation_levels[1]},
|
||||
{storage::IsolationLevelToString((storage::IsolationLevel)2), stats.isolation_levels[2]}};
|
||||
res["durability"] = {{"snapshot_enabled", stats.snapshot_enabled}, {"WAL_enabled", stats.wal_enabled}};
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
#ifdef MG_ENTERPRISE
|
||||
|
||||
using DeleteResult = utils::BasicResult<DeleteError>;
|
||||
|
||||
/**
|
||||
* @brief Multi-database session contexts handler.
|
||||
*/
|
||||
class DbmsHandler {
|
||||
public:
|
||||
using LockT = utils::RWLock;
|
||||
using NewResultT = utils::BasicResult<NewError, DatabaseAccess>;
|
||||
|
||||
/**
|
||||
* @brief Initialize the handler.
|
||||
*
|
||||
* @param configs storage and interpreter configurations
|
||||
* @param auth pointer to the global authenticator
|
||||
* @param recovery_on_startup restore databases (and its content) and authentication data
|
||||
* @param delete_on_drop when dropping delete any associated directories on disk
|
||||
*/
|
||||
DbmsHandler(storage::Config config, auto *auth, bool recovery_on_startup, bool delete_on_drop)
|
||||
: lock_{utils::RWLock::Priority::READ}, default_config_{std::move(config)}, delete_on_drop_(delete_on_drop) {
|
||||
// TODO: Decouple storage config from dbms config
|
||||
// TODO: Save individual db configs inside the kvstore and restore from there
|
||||
storage::UpdatePaths(*default_config_, default_config_->durability.storage_directory / "databases");
|
||||
const auto &db_dir = default_config_->durability.storage_directory;
|
||||
const auto durability_dir = db_dir / ".durability";
|
||||
utils::EnsureDirOrDie(db_dir);
|
||||
utils::EnsureDirOrDie(durability_dir);
|
||||
durability_ = std::make_unique<kvstore::KVStore>(durability_dir);
|
||||
|
||||
// Generate the default database
|
||||
MG_ASSERT(!NewDefault_().HasError(), "Failed while creating the default DB.");
|
||||
|
||||
// Recover previous databases
|
||||
if (recovery_on_startup) {
|
||||
for (const auto &[name, _] : *durability_) {
|
||||
if (name == kDefaultDB) continue; // Already set
|
||||
spdlog::info("Restoring database {}.", name);
|
||||
MG_ASSERT(!New_(name).HasError(), "Failed while creating database {}.", name);
|
||||
spdlog::info("Database {} restored.", name);
|
||||
}
|
||||
} else { // Clear databases from the durability list and auth
|
||||
auto locked_auth = auth->Lock();
|
||||
for (const auto &[name, _] : *durability_) {
|
||||
if (name == kDefaultDB) continue;
|
||||
locked_auth->DeleteDatabase(name);
|
||||
durability_->Delete(name);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Create a new Database associated with the "name" database
|
||||
*
|
||||
* @param name name of the database
|
||||
* @return NewResultT context on success, error on failure
|
||||
*/
|
||||
NewResultT New(const std::string &name) {
|
||||
std::lock_guard<LockT> wr(lock_);
|
||||
return New_(name, name);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Get the context associated with the "name" database
|
||||
*
|
||||
* @param name
|
||||
* @return DatabaseAccess
|
||||
* @throw UnknownDatabaseException if database not found
|
||||
*/
|
||||
DatabaseAccess Get(std::string_view name) {
|
||||
std::shared_lock<LockT> rd(lock_);
|
||||
return Get_(name);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Delete database.
|
||||
*
|
||||
* @param db_name database name
|
||||
* @return DeleteResult error on failure
|
||||
*/
|
||||
DeleteResult Delete(const std::string &db_name) {
|
||||
std::lock_guard<LockT> wr(lock_);
|
||||
if (db_name == kDefaultDB) {
|
||||
// MSG cannot delete the default db
|
||||
return DeleteError::DEFAULT_DB;
|
||||
}
|
||||
|
||||
const auto storage_path = StorageDir_(db_name);
|
||||
if (!storage_path) return DeleteError::NON_EXISTENT;
|
||||
|
||||
// Check if db exists
|
||||
try {
|
||||
// Low level handlers
|
||||
if (!db_handler_.Delete(db_name)) {
|
||||
return DeleteError::USING;
|
||||
}
|
||||
} catch (utils::BasicException &) {
|
||||
return DeleteError::NON_EXISTENT;
|
||||
}
|
||||
|
||||
// Remove from durability list
|
||||
if (durability_) durability_->Delete(db_name);
|
||||
|
||||
// Delete disk storage
|
||||
if (delete_on_drop_) {
|
||||
std::error_code ec;
|
||||
(void)std::filesystem::remove_all(*storage_path, ec);
|
||||
if (ec) {
|
||||
spdlog::error("Failed to clean disk while deleting database \"{}\".", db_name);
|
||||
defunct_dbs_.emplace(db_name);
|
||||
return DeleteError::DISK_FAIL;
|
||||
}
|
||||
}
|
||||
|
||||
// Delete from defunct_dbs_ (in case a second delete call was successful)
|
||||
defunct_dbs_.erase(db_name);
|
||||
|
||||
return {}; // Success
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Return all active databases.
|
||||
*
|
||||
* @return std::vector<std::string>
|
||||
*/
|
||||
std::vector<std::string> All() const {
|
||||
std::shared_lock<LockT> rd(lock_);
|
||||
return db_handler_.All();
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Return the statistics all databases.
|
||||
*
|
||||
* @return Statistics
|
||||
*/
|
||||
Statistics Stats() {
|
||||
Statistics stats{};
|
||||
// TODO: Handle overflow?
|
||||
std::shared_lock<LockT> rd(lock_);
|
||||
for (auto &[_, db_gk] : db_handler_) {
|
||||
auto db_acc_opt = db_gk.access();
|
||||
if (!db_acc_opt) continue;
|
||||
auto &db_acc = *db_acc_opt;
|
||||
const auto &info = db_acc->GetInfo();
|
||||
const auto &storage_info = info.storage_info;
|
||||
stats.num_vertex += storage_info.vertex_count;
|
||||
stats.num_edges += storage_info.edge_count;
|
||||
stats.triggers += info.triggers;
|
||||
stats.streams += info.streams;
|
||||
++stats.num_databases;
|
||||
stats.indices += storage_info.label_indices + storage_info.label_property_indices;
|
||||
stats.constraints += storage_info.existence_constraints + storage_info.unique_constraints;
|
||||
++stats.storage_modes[(int)storage_info.storage_mode];
|
||||
++stats.isolation_levels[(int)storage_info.isolation_level];
|
||||
stats.snapshot_enabled += storage_info.durability_snapshot_enabled;
|
||||
stats.wal_enabled += storage_info.durability_wal_enabled;
|
||||
}
|
||||
return stats;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Return a vector with all database info.
|
||||
*
|
||||
* @return std::vector<DatabaseInfo>
|
||||
*/
|
||||
std::vector<DatabaseInfo> Info() {
|
||||
std::vector<DatabaseInfo> res;
|
||||
res.reserve(std::distance(db_handler_.cbegin(), db_handler_.cend()));
|
||||
std::shared_lock<LockT> rd(lock_);
|
||||
for (auto &[_, db_gk] : db_handler_) {
|
||||
auto db_acc_opt = db_gk.access();
|
||||
if (!db_acc_opt) continue;
|
||||
auto &db_acc = *db_acc_opt;
|
||||
res.push_back(db_acc->GetInfo());
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Restore triggers for all currently defined databases.
|
||||
* @note: Triggers can execute query procedures, so we need to reload the modules first and then the triggers
|
||||
*
|
||||
* @param ic global InterpreterContext
|
||||
*/
|
||||
void RestoreTriggers(query::InterpreterContext *ic) {
|
||||
std::lock_guard<LockT> wr(lock_);
|
||||
for (auto &[_, db_gk] : db_handler_) {
|
||||
auto db_acc_opt = db_gk.access();
|
||||
if (!db_acc_opt) continue;
|
||||
auto &db_acc = *db_acc_opt;
|
||||
spdlog::debug("Restoring trigger for database \"{}\"", db_acc->id());
|
||||
auto storage_accessor = db_acc->Access();
|
||||
auto dba = memgraph::query::DbAccessor{storage_accessor.get()};
|
||||
db_acc->trigger_store()->RestoreTriggers(&ic->ast_cache, &dba, ic->config.query, ic->auth_checker);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Restore streams of all currently defined databases.
|
||||
* @note: Stream transformations are using modules, they have to be restored after the query modules are loaded.
|
||||
*
|
||||
* @param ic global InterpreterContext
|
||||
*/
|
||||
void RestoreStreams(query::InterpreterContext *ic) {
|
||||
std::lock_guard<LockT> wr(lock_);
|
||||
for (auto &[_, db_gk] : db_handler_) {
|
||||
auto db_acc = db_gk.access();
|
||||
if (!db_acc) continue;
|
||||
auto *db = db_acc->get();
|
||||
spdlog::debug("Restoring streams for database \"{}\"", db->id());
|
||||
db->streams()->RestoreStreams(*db_acc, ic);
|
||||
}
|
||||
}
|
||||
|
||||
private:
|
||||
/**
|
||||
* @brief return the storage directory of the associated database
|
||||
*
|
||||
* @param name Database name
|
||||
* @return std::optional<std::filesystem::path>
|
||||
*/
|
||||
std::optional<std::filesystem::path> StorageDir_(const std::string &name) {
|
||||
const auto conf = db_handler_.GetConfig(name);
|
||||
if (conf) {
|
||||
return conf->durability.storage_directory;
|
||||
}
|
||||
spdlog::debug("Failed to find storage dir for database \"{}\"", name);
|
||||
return {};
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Create a new Database associated with the "name" database
|
||||
*
|
||||
* @param name name of the database
|
||||
* @return NewResultT context on success, error on failure
|
||||
*/
|
||||
NewResultT New_(const std::string &name) { return New_(name, name); }
|
||||
|
||||
/**
|
||||
* @brief Create a new Database associated with the "name" database
|
||||
*
|
||||
* @param name name of the database
|
||||
* @param storage_subdir undelying RocksDB directory
|
||||
* @return NewResultT context on success, error on failure
|
||||
*/
|
||||
NewResultT New_(const std::string &name, std::filesystem::path storage_subdir) {
|
||||
if (default_config_) {
|
||||
auto config_copy = *default_config_;
|
||||
storage::UpdatePaths(config_copy, default_config_->durability.storage_directory / storage_subdir);
|
||||
return New_(name, config_copy);
|
||||
}
|
||||
spdlog::info("Trying to generate session context without any configurations.");
|
||||
return NewError::NO_CONFIGS;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Create a new Database associated with the "name" database
|
||||
*
|
||||
* @param name name of the database
|
||||
* @param storage_config storage configuration
|
||||
* @return NewResultT context on success, error on failure
|
||||
*/
|
||||
NewResultT New_(const std::string &name, storage::Config &storage_config) {
|
||||
if (defunct_dbs_.contains(name)) {
|
||||
spdlog::warn("Failed to generate database due to the unknown state of the previously defunct database \"{}\".",
|
||||
name);
|
||||
return NewError::DEFUNCT;
|
||||
}
|
||||
|
||||
auto new_db = db_handler_.New(name, storage_config);
|
||||
if (new_db.HasValue()) {
|
||||
// Success
|
||||
if (durability_) durability_->Put(name, "ok"); // TODO: Serialize the configuration?
|
||||
return new_db.GetValue();
|
||||
}
|
||||
return new_db.GetError();
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Create a new Database associated with the default database
|
||||
*
|
||||
* @return NewResultT context on success, error on failure
|
||||
*/
|
||||
NewResultT NewDefault_() {
|
||||
// Create the default DB in the root (this is how it was done pre multi-tenancy)
|
||||
auto res = New_(kDefaultDB, "..");
|
||||
if (res.HasValue()) {
|
||||
// For back-compatibility...
|
||||
// Recreate the dbms layout for the default db and symlink to the root
|
||||
const auto dir = StorageDir_(kDefaultDB);
|
||||
MG_ASSERT(dir, "Failed to find storage path.");
|
||||
const auto main_dir = *dir / "databases" / kDefaultDB;
|
||||
|
||||
if (!std::filesystem::exists(main_dir)) {
|
||||
std::filesystem::create_directory(main_dir);
|
||||
}
|
||||
|
||||
// Force link on-disk directories
|
||||
const auto conf = db_handler_.GetConfig(kDefaultDB);
|
||||
MG_ASSERT(conf, "No configuration for the default database.");
|
||||
const auto &tmp_conf = conf->disk;
|
||||
std::vector<std::filesystem::path> to_link{
|
||||
tmp_conf.main_storage_directory, tmp_conf.label_index_directory,
|
||||
tmp_conf.label_property_index_directory, tmp_conf.unique_constraints_directory,
|
||||
tmp_conf.name_id_mapper_directory, tmp_conf.id_name_mapper_directory,
|
||||
tmp_conf.durability_directory, tmp_conf.wal_directory,
|
||||
};
|
||||
|
||||
// Add in-memory paths
|
||||
// Some directories are redundant (skip those)
|
||||
const std::vector<std::string> skip{".lock", "audit_log", "auth", "databases", "internal_modules", "settings"};
|
||||
for (auto const &item : std::filesystem::directory_iterator{*dir}) {
|
||||
const auto dir_name = std::filesystem::relative(item.path(), item.path().parent_path());
|
||||
if (std::find(skip.begin(), skip.end(), dir_name) != skip.end()) continue;
|
||||
to_link.push_back(item.path());
|
||||
}
|
||||
|
||||
// Symlink to root dir
|
||||
for (auto const &item : to_link) {
|
||||
const auto dir_name = std::filesystem::relative(item, item.parent_path());
|
||||
const auto link = main_dir / dir_name;
|
||||
const auto to = std::filesystem::relative(item, main_dir);
|
||||
if (!std::filesystem::is_symlink(link) && !std::filesystem::exists(link)) {
|
||||
std::filesystem::create_directory_symlink(to, link);
|
||||
} else { // Check existing link
|
||||
std::error_code ec;
|
||||
const auto test_link = std::filesystem::read_symlink(link, ec);
|
||||
if (ec || test_link != to) {
|
||||
MG_ASSERT(false,
|
||||
"Memgraph storage directory incompatible with new version.\n"
|
||||
"Please use a clean directory or remove \"{}\" and try again.",
|
||||
link.string());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Get the DatabaseAccess for the database associated with the "name"
|
||||
*
|
||||
* @param name
|
||||
* @return DatabaseAccess
|
||||
* @throw UnknownDatabaseException if trying to get unknown database
|
||||
*/
|
||||
DatabaseAccess Get_(std::string_view name) {
|
||||
auto db = db_handler_.Get(name);
|
||||
if (db) {
|
||||
return *db;
|
||||
}
|
||||
throw UnknownDatabaseException("Tried to retrieve an unknown database \"{}\".", name);
|
||||
}
|
||||
|
||||
// Should storage objects ever be deleted?
|
||||
mutable LockT lock_; //!< protective lock
|
||||
DatabaseHandler db_handler_; //!< multi-tenancy storage handler
|
||||
std::optional<storage::Config> default_config_; //!< Storage configuration used when creating new databases
|
||||
std::unique_ptr<kvstore::KVStore> durability_; //!< list of active dbs (pointer so we can postpone its creation)
|
||||
std::set<std::string> defunct_dbs_; //!< Databases that are in an unknown state due to various failures
|
||||
bool delete_on_drop_; //!< Flag defining if dropping storage also deletes its directory
|
||||
};
|
||||
#endif
|
||||
|
||||
} // namespace memgraph::dbms
|
||||
@@ -48,6 +48,7 @@ enum class SetForResult : uint8_t {
|
||||
class UnknownSessionException : public utils::BasicException {
|
||||
public:
|
||||
using utils::BasicException::BasicException;
|
||||
SPECIALIZE_GET_EXCEPTION_NAME(UnknownSessionException)
|
||||
};
|
||||
|
||||
/**
|
||||
@@ -58,53 +59,7 @@ class UnknownSessionException : public utils::BasicException {
|
||||
class UnknownDatabaseException : public utils::BasicException {
|
||||
public:
|
||||
using utils::BasicException::BasicException;
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief Session interface used by the DBMS to handle the the active sessions.
|
||||
* @todo Try to remove this dependency from SessionContextHandler. OnDelete could be removed, as it only does an assert.
|
||||
* OnChange could be removed if SetFor returned the pointer and the called then handled the OnChange execution.
|
||||
* However, the interface is very useful to decouple the interpreter's query execution and the sessions themselves.
|
||||
*/
|
||||
class SessionInterface {
|
||||
public:
|
||||
SessionInterface() = default;
|
||||
virtual ~SessionInterface() = default;
|
||||
|
||||
SessionInterface(const SessionInterface &) = default;
|
||||
SessionInterface &operator=(const SessionInterface &) = default;
|
||||
SessionInterface(SessionInterface &&) noexcept = default;
|
||||
SessionInterface &operator=(SessionInterface &&) noexcept = default;
|
||||
|
||||
/**
|
||||
* @brief Return the unique string identifying the session.
|
||||
*
|
||||
* @return std::string
|
||||
*/
|
||||
virtual std::string UUID() const = 0;
|
||||
|
||||
/**
|
||||
* @brief Return the currently active database.
|
||||
*
|
||||
* @return std::string
|
||||
*/
|
||||
virtual std::string GetDatabaseName() const = 0;
|
||||
|
||||
#ifdef MG_ENTERPRISE
|
||||
/**
|
||||
* @brief Gets called on database change.
|
||||
*
|
||||
* @return SetForResult enum (SUCCESS, ALREADY_SET or FAIL)
|
||||
*/
|
||||
virtual dbms::SetForResult OnChange(const std::string &) = 0;
|
||||
|
||||
/**
|
||||
* @brief Callback that gets called on database delete (drop).
|
||||
*
|
||||
* @return true on success
|
||||
*/
|
||||
virtual bool OnDelete(const std::string &) = 0;
|
||||
#endif
|
||||
SPECIALIZE_GET_EXCEPTION_NAME(UnknownDatabaseException)
|
||||
};
|
||||
|
||||
} // namespace memgraph::dbms
|
||||
|
||||
@@ -18,21 +18,21 @@
|
||||
#include <unordered_map>
|
||||
|
||||
#include "global.hpp"
|
||||
#include "utils/exceptions.hpp"
|
||||
#include "utils/gatekeeper.hpp"
|
||||
#include "utils/result.hpp"
|
||||
#include "utils/sync_ptr.hpp"
|
||||
|
||||
namespace memgraph::dbms {
|
||||
|
||||
/**
|
||||
* @brief Generic multi-database content handler.
|
||||
*
|
||||
* @tparam TContext
|
||||
* @tparam TConfig
|
||||
* @tparam T
|
||||
*/
|
||||
template <typename TContext, typename TConfig>
|
||||
template <typename T>
|
||||
class Handler {
|
||||
public:
|
||||
using NewResult = utils::BasicResult<NewError, std::shared_ptr<TContext>>;
|
||||
using NewResult = utils::BasicResult<NewError, typename utils::Gatekeeper<T>::Accessor>;
|
||||
|
||||
/**
|
||||
* @brief Empty Handler constructor.
|
||||
@@ -43,67 +43,65 @@ class Handler {
|
||||
/**
|
||||
* @brief Generate a new context and corresponding configuration.
|
||||
*
|
||||
* @tparam T1 Variadic template of context constructor arguments
|
||||
* @tparam T2 Variadic template of config constructor arguments
|
||||
* @param name Name associated with the new context/config pair
|
||||
* @param args1 Arguments passed (as a tuple) to the context constructor
|
||||
* @param args2 Arguments passed (as a tuple) to the config constructor
|
||||
* @tparam Args Variadic template of constructor arguments of T
|
||||
* @param name Name associated with the new T
|
||||
* @param args Arguments passed to the constructor of T
|
||||
* @return NewResult
|
||||
*/
|
||||
template <typename... T1, typename... T2>
|
||||
NewResult New(std::string name, std::tuple<T1...> args1, std::tuple<T2...> args2) {
|
||||
return New_(name, args1, args2, std::make_index_sequence<sizeof...(T1)>{},
|
||||
std::make_index_sequence<sizeof...(T2)>{});
|
||||
template <typename... Args>
|
||||
NewResult New(std::piecewise_construct_t /* marker */, std::string_view name, Args... args) {
|
||||
// Make sure the emplace will succeed, since we don't want to create temporary objects that could break something
|
||||
if (!Has(name)) {
|
||||
auto [itr, _] = items_.emplace(std::piecewise_construct, std::forward_as_tuple(name),
|
||||
std::forward_as_tuple(std::forward<Args>(args)...));
|
||||
auto db_acc = itr->second.access();
|
||||
if (db_acc) return std::move(*db_acc);
|
||||
return NewError::DEFUNCT;
|
||||
}
|
||||
spdlog::info("Item with name \"{}\" already exists.", name);
|
||||
return NewError::EXISTS;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Get pointer to context.
|
||||
*
|
||||
* @param name Name associated with the wanted context
|
||||
* @return std::optional<std::shared_ptr<TContext>>
|
||||
* @return std::optional<typename utils::Gatekeeper<T>::Accessor>
|
||||
*/
|
||||
std::optional<std::shared_ptr<TContext>> Get(const std::string &name) {
|
||||
std::optional<typename utils::Gatekeeper<T>::Accessor> Get(std::string_view name) {
|
||||
if (auto search = items_.find(name); search != items_.end()) {
|
||||
return search->second.get();
|
||||
return search->second.access();
|
||||
}
|
||||
return {};
|
||||
return std::nullopt;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Get the config.
|
||||
* @brief Delete the context associated with the name.
|
||||
*
|
||||
* @param name Name associated with the wanted config
|
||||
* @return std::optional<TConfig>
|
||||
*/
|
||||
std::optional<TConfig> GetConfig(const std::string &name) const {
|
||||
if (auto search = items_.find(name); search != items_.end()) {
|
||||
return search->second.config();
|
||||
}
|
||||
return {};
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Delete the context/config pair associated with the name.
|
||||
*
|
||||
* @param name Name associated with the context/config pair to delete
|
||||
* @param name Name associated with the context to delete
|
||||
* @return true on success
|
||||
* @throw BasicException
|
||||
*/
|
||||
bool Delete(const std::string &name) {
|
||||
if (auto itr = items_.find(name); itr != items_.end()) {
|
||||
itr->second.DestroyAndSync();
|
||||
items_.erase(itr);
|
||||
return true;
|
||||
auto db_acc = itr->second.access();
|
||||
if (db_acc && db_acc->try_delete()) {
|
||||
db_acc->reset();
|
||||
items_.erase(itr);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
return false;
|
||||
throw utils::BasicException("Unknown item \"{}\".", name);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Check if a name is already used.
|
||||
*
|
||||
* @param name Name to check
|
||||
* @return true if a context/config pair is already associated with the name
|
||||
* @return true if a T is already associated with the name
|
||||
*/
|
||||
bool Has(const std::string &name) const { return items_.find(name) != items_.end(); }
|
||||
bool Has(std::string_view name) const { return items_.find(name) != items_.end(); }
|
||||
|
||||
auto begin() { return items_.begin(); }
|
||||
auto end() { return items_.end(); }
|
||||
@@ -112,31 +110,16 @@ class Handler {
|
||||
auto cbegin() const { return items_.cbegin(); }
|
||||
auto cend() const { return items_.cend(); }
|
||||
|
||||
private:
|
||||
/**
|
||||
* @brief Lower level handler that hides some ugly code.
|
||||
*
|
||||
* @tparam T1 Variadic template of context constructor arguments
|
||||
* @tparam T2 Variadic template of config constructor arguments
|
||||
* @tparam I1 List of indexes associated with the first tuple
|
||||
* @tparam I2 List of indexes associated with the second tuple
|
||||
*/
|
||||
template <typename... T1, typename... T2, std::size_t... I1, std::size_t... I2>
|
||||
NewResult New_(std::string name, std::tuple<T1...> &args1, std::tuple<T2...> &args2,
|
||||
std::integer_sequence<std::size_t, I1...> /*not-used*/,
|
||||
std::integer_sequence<std::size_t, I2...> /*not-used*/) {
|
||||
// Make sure the emplace will succeed, since we don't want to create temporary objects that could break something
|
||||
if (!Has(name)) {
|
||||
auto [itr, _] = items_.emplace(std::piecewise_construct, std::forward_as_tuple(name),
|
||||
std::forward_as_tuple(TConfig{std::forward<T1>(std::get<I1>(args1))...},
|
||||
std::forward<T2>(std::get<I2>(args2))...));
|
||||
return itr->second.get();
|
||||
}
|
||||
spdlog::info("Item with name \"{}\" already exists.", name);
|
||||
return NewError::EXISTS;
|
||||
}
|
||||
struct string_hash {
|
||||
using is_transparent = void;
|
||||
[[nodiscard]] size_t operator()(const char *s) const { return std::hash<std::string_view>{}(s); }
|
||||
[[nodiscard]] size_t operator()(std::string_view s) const { return std::hash<std::string_view>{}(s); }
|
||||
[[nodiscard]] size_t operator()(const std::string &s) const { return std::hash<std::string>{}(s); }
|
||||
};
|
||||
|
||||
std::unordered_map<std::string, utils::SyncPtr<TContext, TConfig>> items_; //!< map to all active items
|
||||
private:
|
||||
std::unordered_map<std::string, utils::Gatekeeper<T>, string_hash, std::equal_to<>>
|
||||
items_; //!< map to all active items
|
||||
};
|
||||
|
||||
} // namespace memgraph::dbms
|
||||
|
||||
@@ -1,106 +0,0 @@
|
||||
// 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
|
||||
|
||||
#ifdef MG_ENTERPRISE
|
||||
|
||||
#include "global.hpp"
|
||||
#include "query/auth_checker.hpp"
|
||||
#include "query/config.hpp"
|
||||
#include "query/interpreter.hpp"
|
||||
#include "storage/v2/storage.hpp"
|
||||
|
||||
#include "handler.hpp"
|
||||
|
||||
namespace memgraph::dbms {
|
||||
|
||||
/**
|
||||
* @brief Simple class that adds useful information to the query's InterpreterContext
|
||||
*
|
||||
* @tparam T Multi-database handler type
|
||||
*/
|
||||
template <typename T>
|
||||
class ExpandedInterpContext : public query::InterpreterContext {
|
||||
public:
|
||||
template <typename... TArgs>
|
||||
explicit ExpandedInterpContext(T &ref, TArgs &&...args)
|
||||
: query::InterpreterContext(std::forward<TArgs>(args)...), sc_handler_(ref) {}
|
||||
|
||||
T &sc_handler_; //!< Multi-database/SessionContext handler (used in some queries)
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief Simple structure that expands on the query's InterpreterConfig
|
||||
*
|
||||
*/
|
||||
struct ExpandedInterpConfig {
|
||||
storage::Config storage_config; //!< Storage configuration
|
||||
query::InterpreterConfig interp_config; //!< Interpreter configuration
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief Multi-database interpreter context handler
|
||||
*
|
||||
* @tparam TSCHandler High-level multi-database/SessionContext handler type
|
||||
*/
|
||||
template <typename TSCHandler>
|
||||
class InterpContextHandler : public Handler<ExpandedInterpContext<TSCHandler>, ExpandedInterpConfig> {
|
||||
public:
|
||||
using InterpContextT = ExpandedInterpContext<TSCHandler>;
|
||||
using HandlerT = Handler<InterpContextT, ExpandedInterpConfig>;
|
||||
|
||||
/**
|
||||
* @brief Generate a new interpreter context associated with the passed name.
|
||||
*
|
||||
* @param name Name associating the new interpreter context
|
||||
* @param sc_handler Multi-database/SessionContext handler used (some queries might use it)
|
||||
* @param db Storage associated with the interpreter context
|
||||
* @param config Interpreter's configuration
|
||||
* @param dir Directory used by the interpreter
|
||||
* @param auth_handler AuthQueryHandler used
|
||||
* @param auth_checker AuthChecker used
|
||||
* @return HandlerT::NewResult
|
||||
*/
|
||||
typename HandlerT::NewResult New(const std::string &name, TSCHandler &sc_handler, storage::Config storage_config,
|
||||
const query::InterpreterConfig &interpreter_config,
|
||||
query::AuthQueryHandler &auth_handler, query::AuthChecker &auth_checker) {
|
||||
// Check if compatible with the existing interpreters
|
||||
if (std::any_of(HandlerT::cbegin(), HandlerT::cend(), [&](const auto &elem) {
|
||||
const auto &config = elem.second.config().storage_config;
|
||||
return config.durability.storage_directory == storage_config.durability.storage_directory;
|
||||
})) {
|
||||
spdlog::info("Tried to generate a new context using claimed directory and/or storage.");
|
||||
return NewError::EXISTS;
|
||||
}
|
||||
const auto dir = storage_config.durability.storage_directory;
|
||||
storage_config.name = name; // Set storage id via config
|
||||
return HandlerT::New(
|
||||
name, std::forward_as_tuple(storage_config, interpreter_config),
|
||||
std::forward_as_tuple(sc_handler, storage_config, interpreter_config, dir, &auth_handler, &auth_checker));
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief All currently active storage.
|
||||
*
|
||||
* @return std::vector<std::string>
|
||||
*/
|
||||
std::vector<std::string> All() const {
|
||||
std::vector<std::string> res;
|
||||
res.reserve(std::distance(HandlerT::cbegin(), HandlerT::cend()));
|
||||
std::for_each(HandlerT::cbegin(), HandlerT::cend(), [&](const auto &elem) { res.push_back(elem.first); });
|
||||
return res;
|
||||
}
|
||||
};
|
||||
|
||||
} // namespace memgraph::dbms
|
||||
|
||||
#endif
|
||||
@@ -1,61 +0,0 @@
|
||||
// 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 "auth/auth.hpp"
|
||||
#include "query/interpreter.hpp"
|
||||
#include "storage/v2/storage.hpp"
|
||||
#include "utils/synchronized.hpp"
|
||||
|
||||
#if MG_ENTERPRISE
|
||||
#include "audit/log.hpp"
|
||||
#endif
|
||||
namespace memgraph::dbms {
|
||||
|
||||
/**
|
||||
* @brief Structure encapsulating storage and interpreter context.
|
||||
*
|
||||
* @note Each session contains a copy.
|
||||
*/
|
||||
struct SessionContext {
|
||||
// Explicit constructor here to ensure that pointers to all objects are
|
||||
// supplied.
|
||||
|
||||
SessionContext(std::shared_ptr<memgraph::query::InterpreterContext> interpreter_context, std::string run,
|
||||
memgraph::utils::Synchronized<memgraph::auth::Auth, memgraph::utils::WritePrioritizedRWLock> *auth
|
||||
#ifdef MG_ENTERPRISE
|
||||
,
|
||||
memgraph::audit::Log *audit_log
|
||||
#endif
|
||||
)
|
||||
: interpreter_context(interpreter_context),
|
||||
run_id(run),
|
||||
auth(auth)
|
||||
#ifdef MG_ENTERPRISE
|
||||
,
|
||||
audit_log(audit_log)
|
||||
#endif
|
||||
{
|
||||
}
|
||||
|
||||
std::shared_ptr<memgraph::query::InterpreterContext> interpreter_context;
|
||||
std::string run_id;
|
||||
|
||||
// std::shared_ptr<AuthContext> auth_context;
|
||||
memgraph::utils::Synchronized<memgraph::auth::Auth, memgraph::utils::WritePrioritizedRWLock> *auth;
|
||||
|
||||
#ifdef MG_ENTERPRISE
|
||||
memgraph::audit::Log *audit_log;
|
||||
#endif
|
||||
};
|
||||
|
||||
} // namespace memgraph::dbms
|
||||
@@ -1,603 +0,0 @@
|
||||
// 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 <algorithm>
|
||||
#include <concepts>
|
||||
#include <cstdint>
|
||||
#include <filesystem>
|
||||
#include <memory>
|
||||
#include <mutex>
|
||||
#include <optional>
|
||||
#include <ostream>
|
||||
#include <stdexcept>
|
||||
#include <system_error>
|
||||
#include <unordered_map>
|
||||
|
||||
#include "constants.hpp"
|
||||
#include "global.hpp"
|
||||
#include "interp_handler.hpp"
|
||||
#include "query/auth_checker.hpp"
|
||||
#include "query/config.hpp"
|
||||
#include "query/interpreter.hpp"
|
||||
#include "session_context.hpp"
|
||||
#include "spdlog/spdlog.h"
|
||||
#include "storage/v2/durability/durability.hpp"
|
||||
#include "storage/v2/durability/paths.hpp"
|
||||
#include "utils/exceptions.hpp"
|
||||
#include "utils/file.hpp"
|
||||
#include "utils/logging.hpp"
|
||||
#include "utils/result.hpp"
|
||||
#include "utils/rw_lock.hpp"
|
||||
#include "utils/synchronized.hpp"
|
||||
#include "utils/uuid.hpp"
|
||||
|
||||
#include "handler.hpp"
|
||||
|
||||
namespace memgraph::dbms {
|
||||
|
||||
#ifdef MG_ENTERPRISE
|
||||
|
||||
using DeleteResult = utils::BasicResult<DeleteError>;
|
||||
|
||||
/**
|
||||
* @brief Multi-database session contexts handler.
|
||||
*/
|
||||
class SessionContextHandler {
|
||||
public:
|
||||
using StorageT = storage::Storage;
|
||||
using StorageConfigT = storage::Config;
|
||||
using LockT = utils::RWLock;
|
||||
using NewResultT = utils::BasicResult<NewError, SessionContext>;
|
||||
|
||||
struct Config {
|
||||
StorageConfigT storage_config; //!< Storage configuration
|
||||
query::InterpreterConfig interp_config; //!< Interpreter context configuration
|
||||
std::function<void(utils::Synchronized<auth::Auth, utils::WritePrioritizedRWLock> *,
|
||||
std::unique_ptr<query::AuthQueryHandler> &, std::unique_ptr<query::AuthChecker> &)>
|
||||
glue_auth;
|
||||
};
|
||||
|
||||
struct Statistics {
|
||||
uint64_t num_vertex; //!< Sum of vertexes in every database
|
||||
uint64_t num_edges; //!< Sum of edges in every database
|
||||
uint64_t num_databases; //! number of isolated databases
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief Initialize the handler.
|
||||
*
|
||||
* @param audit_log pointer to the audit logger (ENTERPRISE only)
|
||||
* @param configs storage and interpreter configurations
|
||||
* @param recovery_on_startup restore databases (and its content) and authentication data
|
||||
*/
|
||||
SessionContextHandler(memgraph::audit::Log &audit_log, Config configs, bool recovery_on_startup, bool delete_on_drop)
|
||||
: lock_{utils::RWLock::Priority::READ},
|
||||
default_configs_(configs),
|
||||
run_id_{utils::GenerateUUID()},
|
||||
audit_log_(&audit_log),
|
||||
delete_on_drop_(delete_on_drop) {
|
||||
const auto &root = configs.storage_config.durability.storage_directory;
|
||||
utils::EnsureDirOrDie(root);
|
||||
// Verify that the user that started the process is the same user that is
|
||||
// the owner of the storage directory.
|
||||
storage::durability::VerifyStorageDirectoryOwnerAndProcessUserOrDie(root);
|
||||
|
||||
// Create the lock file and open a handle to it. This will crash the
|
||||
// database if it can't open the file for writing or if any other process is
|
||||
// holding the file opened.
|
||||
lock_file_path_ = root / ".lock";
|
||||
lock_file_handle_.Open(lock_file_path_, utils::OutputFile::Mode::OVERWRITE_EXISTING);
|
||||
MG_ASSERT(lock_file_handle_.AcquireLock(),
|
||||
"Couldn't acquire lock on the storage directory {}"
|
||||
"!\nAnother Memgraph process is currently running with the same "
|
||||
"storage directory, please stop it first before starting this "
|
||||
"process!",
|
||||
root);
|
||||
|
||||
// TODO: Figure out if this is needed/wanted
|
||||
// Clear auth database since we are not recovering
|
||||
// if (!recovery_on_startup) {
|
||||
// const auto &auth_dir = root / "auth";
|
||||
// // Backup if auth present
|
||||
// if (utils::DirExists(auth_dir)) {
|
||||
// auto backup_dir = root / storage::durability::kBackupDirectory;
|
||||
// std::error_code error_code;
|
||||
// utils::EnsureDirOrDie(backup_dir);
|
||||
// std::error_code ec;
|
||||
// const auto now = std::chrono::system_clock::now();
|
||||
// std::ostringstream os;
|
||||
// os << now.time_since_epoch().count();
|
||||
// std::filesystem::rename(auth_dir, backup_dir / ("auth-" + os.str()), ec);
|
||||
// MG_ASSERT(!ec, "Couldn't backup auth directory because of: {}", ec.message());
|
||||
// spdlog::warn(
|
||||
// "Since Memgraph was not supposed to recover on startup the authentication files will be "
|
||||
// "overwritten. To prevent important data loss, Memgraph has stored those files into .backup directory "
|
||||
// "inside the storage directory.");
|
||||
// }
|
||||
|
||||
// // Clear
|
||||
// if (std::filesystem::exists(auth_dir)) {
|
||||
// std::filesystem::remove_all(auth_dir);
|
||||
// }
|
||||
// }
|
||||
|
||||
// Lazy initialization of auth_
|
||||
auth_ = std::make_unique<utils::Synchronized<auth::Auth, utils::WritePrioritizedRWLock>>(root / "auth");
|
||||
configs.glue_auth(auth_.get(), auth_handler_, auth_checker_);
|
||||
|
||||
// TODO: Decouple storage config from dbms config
|
||||
// TODO: Save individual db configs inside the kvstore and restore from there
|
||||
storage::UpdatePaths(default_configs_->storage_config,
|
||||
default_configs_->storage_config.durability.storage_directory / "databases");
|
||||
const auto &db_dir = default_configs_->storage_config.durability.storage_directory;
|
||||
const auto durability_dir = db_dir / ".durability";
|
||||
utils::EnsureDirOrDie(db_dir);
|
||||
utils::EnsureDirOrDie(durability_dir);
|
||||
durability_ = std::make_unique<kvstore::KVStore>(durability_dir);
|
||||
|
||||
// Generate the default database
|
||||
MG_ASSERT(!NewDefault_().HasError(), "Failed while creating the default DB.");
|
||||
|
||||
// Recover previous databases
|
||||
if (recovery_on_startup) {
|
||||
for (const auto &[name, _] : *durability_) {
|
||||
if (name == kDefaultDB) continue; // Already set
|
||||
spdlog::info("Restoring database {}.", name);
|
||||
MG_ASSERT(!New_(name).HasError(), "Failed while creating database {}.", name);
|
||||
spdlog::info("Database {} restored.", name);
|
||||
}
|
||||
} else { // Clear databases from the durability list and auth
|
||||
auto locked_auth = auth_->Lock();
|
||||
for (const auto &[name, _] : *durability_) {
|
||||
if (name == kDefaultDB) continue;
|
||||
locked_auth->DeleteDatabase(name);
|
||||
durability_->Delete(name);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void Shutdown() {
|
||||
for (auto &ic : interp_handler_) memgraph::query::Shutdown(ic.second.get().get());
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Create a new SessionContext associated with the "name" database
|
||||
*
|
||||
* @param name name of the database
|
||||
* @return NewResultT context on success, error on failure
|
||||
*/
|
||||
NewResultT New(const std::string &name) {
|
||||
std::lock_guard<LockT> wr(lock_);
|
||||
return New_(name, name);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Get the context associated with the "name" database
|
||||
*
|
||||
* @param name
|
||||
* @return SessionContext
|
||||
* @throw UnknownDatabaseException if getting unknown database
|
||||
*/
|
||||
SessionContext Get(const std::string &name) {
|
||||
std::shared_lock<LockT> rd(lock_);
|
||||
return Get_(name);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Set the undelying database for a particular session.
|
||||
*
|
||||
* @param uuid unique session identifier
|
||||
* @param db_name unique database name
|
||||
* @return SetForResult enum
|
||||
* @throws UnknownDatabaseException, UnknownSessionException or anything OnChange throws
|
||||
*/
|
||||
SetForResult SetFor(const std::string &uuid, const std::string &db_name) {
|
||||
std::shared_lock<LockT> rd(lock_);
|
||||
(void)Get_(
|
||||
db_name); // throws if db doesn't exist (TODO: Better to pass it via OnChange - but injecting dependency)
|
||||
try {
|
||||
auto &s = sessions_.at(uuid);
|
||||
return s.OnChange(db_name);
|
||||
} catch (std::out_of_range &) {
|
||||
throw UnknownSessionException("Unknown session \"{}\"", uuid);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Set the undelying database from a session itself. SessionContext handler.
|
||||
*
|
||||
* @param db_name unique database name
|
||||
* @param handler function that gets called in place with the appropriate SessionContext
|
||||
* @return SetForResult enum
|
||||
*/
|
||||
template <typename THandler>
|
||||
requires std::invocable<THandler, SessionContext> SetForResult SetInPlace(const std::string &db_name,
|
||||
THandler handler) {
|
||||
std::shared_lock<LockT> rd(lock_);
|
||||
return handler(Get_(db_name));
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Call void handler under a shared lock.
|
||||
*
|
||||
* @param handler function that gets called in place
|
||||
*/
|
||||
template <typename THandler>
|
||||
requires std::invocable<THandler>
|
||||
void CallInPlace(THandler handler) {
|
||||
std::shared_lock<LockT> rd(lock_);
|
||||
handler();
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Register an active session (used to handle callbacks).
|
||||
*
|
||||
* @param session
|
||||
* @return true on success
|
||||
*/
|
||||
bool Register(SessionInterface &session) {
|
||||
std::lock_guard<LockT> wr(lock_);
|
||||
auto [_, success] = sessions_.emplace(session.UUID(), session);
|
||||
return success;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Delete a session.
|
||||
*
|
||||
* @param session
|
||||
*/
|
||||
bool Delete(const SessionInterface &session) {
|
||||
std::lock_guard<LockT> wr(lock_);
|
||||
return sessions_.erase(session.UUID()) > 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Delete database.
|
||||
*
|
||||
* @param db_name database name
|
||||
* @return DeleteResult error on failure
|
||||
*/
|
||||
DeleteResult Delete(const std::string &db_name) {
|
||||
std::lock_guard<LockT> wr(lock_);
|
||||
if (db_name == kDefaultDB) {
|
||||
// MSG cannot delete the default db
|
||||
return DeleteError::DEFAULT_DB;
|
||||
}
|
||||
// Check if db exists
|
||||
try {
|
||||
auto sc = Get_(db_name);
|
||||
// Check if a session is using the db
|
||||
if (!sc.interpreter_context->interpreters->empty()) {
|
||||
return DeleteError::USING;
|
||||
}
|
||||
} catch (UnknownDatabaseException &) {
|
||||
return DeleteError::NON_EXISTENT;
|
||||
}
|
||||
|
||||
// High level handlers
|
||||
for (auto &[_, s] : sessions_) {
|
||||
if (!s.OnDelete(db_name)) {
|
||||
spdlog::error("Partial failure while deleting database \"{}\".", db_name);
|
||||
defunct_dbs_.emplace(db_name);
|
||||
return DeleteError::FAIL;
|
||||
}
|
||||
}
|
||||
|
||||
// Low level handlers
|
||||
const auto storage_path = StorageDir_(db_name);
|
||||
MG_ASSERT(storage_path, "Missing storage for {}", db_name);
|
||||
if (!interp_handler_.Delete(db_name)) {
|
||||
spdlog::error("Partial failure while deleting database \"{}\".", db_name);
|
||||
defunct_dbs_.emplace(db_name);
|
||||
return DeleteError::FAIL;
|
||||
}
|
||||
|
||||
// Remove from auth
|
||||
auth_->Lock()->DeleteDatabase(db_name);
|
||||
// Remove from durability list
|
||||
if (durability_) durability_->Delete(db_name);
|
||||
|
||||
// Delete disk storage
|
||||
if (delete_on_drop_) {
|
||||
std::error_code ec;
|
||||
(void)std::filesystem::remove_all(*storage_path, ec);
|
||||
if (ec) {
|
||||
spdlog::error("Failed to clean disk while deleting database \"{}\".", db_name);
|
||||
defunct_dbs_.emplace(db_name);
|
||||
return DeleteError::DISK_FAIL;
|
||||
}
|
||||
}
|
||||
|
||||
// Delete from defunct_dbs_ (in case a second delete call was successful)
|
||||
defunct_dbs_.erase(db_name);
|
||||
|
||||
return {}; // Success
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Set the default configurations.
|
||||
*
|
||||
* @param configs storage, interpreter and authorization configurations
|
||||
*/
|
||||
void SetDefaultConfigs(Config configs) {
|
||||
std::lock_guard<LockT> wr(lock_);
|
||||
default_configs_ = configs;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Get the default configurations.
|
||||
*
|
||||
* @return std::optional<Config>
|
||||
*/
|
||||
std::optional<Config> GetDefaultConfigs() const {
|
||||
std::shared_lock<LockT> rd(lock_);
|
||||
return default_configs_;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Return all active databases.
|
||||
*
|
||||
* @return std::vector<std::string>
|
||||
*/
|
||||
std::vector<std::string> All() const {
|
||||
std::shared_lock<LockT> rd(lock_);
|
||||
return interp_handler_.All();
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Return the number of vertex across all databases.
|
||||
*
|
||||
* @return uint64_t
|
||||
*/
|
||||
Statistics Info() const {
|
||||
// TODO: Handle overflow
|
||||
uint64_t nv = 0;
|
||||
uint64_t ne = 0;
|
||||
std::shared_lock<LockT> rd(lock_);
|
||||
const uint64_t ndb = std::distance(interp_handler_.cbegin(), interp_handler_.cend());
|
||||
for (const auto &ic : interp_handler_) {
|
||||
const auto &info = ic.second.get()->db->GetInfo();
|
||||
nv += info.vertex_count;
|
||||
ne += info.edge_count;
|
||||
}
|
||||
return {nv, ne, ndb};
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Return the currently active database for a particular session.
|
||||
*
|
||||
* @param uuid session's unique identifier
|
||||
* @return std::string name of the database
|
||||
* @throw
|
||||
*/
|
||||
std::string Current(const std::string &uuid) const {
|
||||
std::shared_lock<LockT> rd(lock_);
|
||||
return sessions_.at(uuid).GetDatabaseName();
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Restore triggers for all currently defined databases.
|
||||
* @note: Triggers can execute query procedures, so we need to reload the modules first and then the triggers
|
||||
*/
|
||||
void RestoreTriggers() {
|
||||
std::lock_guard<LockT> wr(lock_);
|
||||
for (auto &ic_itr : interp_handler_) {
|
||||
auto ic = ic_itr.second.get();
|
||||
spdlog::debug("Restoring trigger for database \"{}\"", ic->db->id());
|
||||
auto storage_accessor = ic->db->Access();
|
||||
auto dba = memgraph::query::DbAccessor{storage_accessor.get()};
|
||||
ic->trigger_store.RestoreTriggers(&ic->ast_cache, &dba, ic->config.query, ic->auth_checker);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Restore streams of all currently defined databases.
|
||||
* @note: Stream transformations are using modules, they have to be restored after the query modules are loaded.
|
||||
*/
|
||||
void RestoreStreams() {
|
||||
std::lock_guard<LockT> wr(lock_);
|
||||
for (auto &ic_itr : interp_handler_) {
|
||||
auto ic = ic_itr.second.get();
|
||||
spdlog::debug("Restoring streams for database \"{}\"", ic->db->id());
|
||||
ic->streams.RestoreStreams();
|
||||
}
|
||||
}
|
||||
|
||||
private:
|
||||
std::optional<std::filesystem::path> StorageDir_(const std::string &name) const {
|
||||
const auto conf = interp_handler_.GetConfig(name);
|
||||
if (conf) {
|
||||
return conf->storage_config.durability.storage_directory;
|
||||
}
|
||||
spdlog::debug("Failed to find storage dir for database \"{}\"", name);
|
||||
return {};
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Create a new SessionContext associated with the "name" database
|
||||
*
|
||||
* @param name name of the database
|
||||
* @return NewResultT context on success, error on failure
|
||||
*/
|
||||
NewResultT New_(const std::string &name) { return New_(name, name); }
|
||||
|
||||
/**
|
||||
* @brief Create a new SessionContext associated with the "name" database
|
||||
*
|
||||
* @param name name of the database
|
||||
* @param storage_subdir undelying RocksDB directory
|
||||
* @return NewResultT context on success, error on failure
|
||||
*/
|
||||
NewResultT New_(const std::string &name, std::filesystem::path storage_subdir) {
|
||||
if (default_configs_) {
|
||||
auto storage = default_configs_->storage_config;
|
||||
storage::UpdatePaths(storage, storage.durability.storage_directory / storage_subdir);
|
||||
return New_(name, storage, default_configs_->interp_config);
|
||||
}
|
||||
spdlog::info("Trying to generate session context without any configurations.");
|
||||
return NewError::NO_CONFIGS;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Create a new SessionContext associated with the "name" database
|
||||
*
|
||||
* @param name name of the database
|
||||
* @param storage_config storage configuration
|
||||
* @param inter_config interpreter configuration
|
||||
* @return NewResultT context on success, error on failure
|
||||
*/
|
||||
NewResultT New_(const std::string &name, StorageConfigT &storage_config, query::InterpreterConfig &inter_config/*,
|
||||
const std::string &ah_flags*/) {
|
||||
MG_ASSERT(auth_handler_, "No high level AuthQueryHandler has been supplied.");
|
||||
MG_ASSERT(auth_checker_, "No high level AuthChecker has been supplied.");
|
||||
|
||||
if (defunct_dbs_.contains(name)) {
|
||||
spdlog::warn("Failed to generate database due to the unknown state of the previously defunct database \"{}\".",
|
||||
name);
|
||||
return NewError::DEFUNCT;
|
||||
}
|
||||
|
||||
auto new_interp = interp_handler_.New(name, *this, storage_config, inter_config, *auth_handler_, *auth_checker_);
|
||||
|
||||
if (new_interp.HasValue()) {
|
||||
// Success
|
||||
if (durability_) durability_->Put(name, "ok");
|
||||
return SessionContext{new_interp.GetValue(), run_id_, auth_.get(), audit_log_};
|
||||
}
|
||||
return new_interp.GetError();
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Create a new SessionContext associated with the default database
|
||||
*
|
||||
* @return NewResultT context on success, error on failure
|
||||
*/
|
||||
NewResultT NewDefault_() {
|
||||
// Create the default DB in the root (this is how it was done pre multi-tenancy)
|
||||
auto res = New_(kDefaultDB, "..");
|
||||
if (res.HasValue()) {
|
||||
// For back-compatibility...
|
||||
// Recreate the dbms layout for the default db and symlink to the root
|
||||
const auto dir = StorageDir_(kDefaultDB);
|
||||
MG_ASSERT(dir, "Failed to find storage path.");
|
||||
const auto main_dir = *dir / "databases" / kDefaultDB;
|
||||
|
||||
if (!std::filesystem::exists(main_dir)) {
|
||||
std::filesystem::create_directory(main_dir);
|
||||
}
|
||||
|
||||
// Force link on-disk directories
|
||||
const auto conf = interp_handler_.GetConfig(kDefaultDB);
|
||||
MG_ASSERT(conf, "No configuration for the default database.");
|
||||
const auto &tmp_conf = conf->storage_config.disk;
|
||||
std::vector<std::filesystem::path> to_link{
|
||||
tmp_conf.main_storage_directory, tmp_conf.label_index_directory,
|
||||
tmp_conf.label_property_index_directory, tmp_conf.unique_constraints_directory,
|
||||
tmp_conf.name_id_mapper_directory, tmp_conf.id_name_mapper_directory,
|
||||
tmp_conf.durability_directory, tmp_conf.wal_directory,
|
||||
};
|
||||
|
||||
// Add in-memory paths
|
||||
// Some directories are redundant (skip those)
|
||||
const std::vector<std::string> skip{".lock", "audit_log", "auth", "databases", "internal_modules", "settings"};
|
||||
for (auto const &item : std::filesystem::directory_iterator{*dir}) {
|
||||
const auto dir_name = std::filesystem::relative(item.path(), item.path().parent_path());
|
||||
if (std::find(skip.begin(), skip.end(), dir_name) != skip.end()) continue;
|
||||
to_link.push_back(item.path());
|
||||
}
|
||||
|
||||
// Symlink to root dir
|
||||
for (auto const &item : to_link) {
|
||||
const auto dir_name = std::filesystem::relative(item, item.parent_path());
|
||||
const auto link = main_dir / dir_name;
|
||||
const auto to = std::filesystem::relative(item, main_dir);
|
||||
if (!std::filesystem::is_symlink(link) && !std::filesystem::exists(link)) {
|
||||
std::filesystem::create_directory_symlink(to, link);
|
||||
} else { // Check existing link
|
||||
std::error_code ec;
|
||||
const auto test_link = std::filesystem::read_symlink(link, ec);
|
||||
if (ec || test_link != to) {
|
||||
MG_ASSERT(false,
|
||||
"Memgraph storage directory incompatible with new version.\n"
|
||||
"Please use a clean directory or remove \"{}\" and try again.",
|
||||
link.string());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Get the context associated with the "name" database
|
||||
*
|
||||
* @param name
|
||||
* @return SessionContext
|
||||
* @throw UnknownDatabaseException if trying to get unknown database
|
||||
*/
|
||||
SessionContext Get_(const std::string &name) {
|
||||
auto interp = interp_handler_.Get(name);
|
||||
if (interp) {
|
||||
return SessionContext{*interp, run_id_, auth_.get(), audit_log_};
|
||||
}
|
||||
throw UnknownDatabaseException("Tried to retrieve an unknown database \"{}\".", name);
|
||||
}
|
||||
|
||||
// Should storage objects ever be deleted?
|
||||
mutable LockT lock_; //!< protective lock
|
||||
std::filesystem::path lock_file_path_; //!< Lock file protecting the main storage
|
||||
utils::OutputFile lock_file_handle_; //!< Handler the lock (crash if already open)
|
||||
InterpContextHandler<SessionContextHandler> interp_handler_; //!< multi-tenancy interpreter handler
|
||||
// AuthContextHandler auth_handler_; //!< multi-tenancy authorization handler (currently we use a single global
|
||||
// auth)
|
||||
std::unique_ptr<utils::Synchronized<auth::Auth, utils::WritePrioritizedRWLock>> auth_;
|
||||
std::unique_ptr<query::AuthQueryHandler> auth_handler_;
|
||||
std::unique_ptr<query::AuthChecker> auth_checker_;
|
||||
std::optional<Config> default_configs_; //!< default storage and interpreter configurations
|
||||
const std::string run_id_; //!< run's unique identifier (auto generated)
|
||||
memgraph::audit::Log *audit_log_; //!< pointer to the audit logger
|
||||
std::unordered_map<std::string, SessionInterface &> sessions_; //!< map of active/registered sessions
|
||||
std::unique_ptr<kvstore::KVStore> durability_; //!< list of active dbs (pointer so we can postpone its creation)
|
||||
|
||||
std::set<std::string> defunct_dbs_; //!< Databases that are in an unknown state due to various failures
|
||||
bool delete_on_drop_; //!< Flag defining if dropping storage also deletes its directory
|
||||
public:
|
||||
static SessionContextHandler &ExtractSCH(query::InterpreterContext *interpreter_context) {
|
||||
return static_cast<typename decltype(interp_handler_)::InterpContextT *>(interpreter_context)->sc_handler_;
|
||||
}
|
||||
};
|
||||
|
||||
#else
|
||||
/**
|
||||
* @brief Initialize the handler.
|
||||
*
|
||||
* @param auth pointer to the authenticator
|
||||
* @param configs storage and interpreter configurations
|
||||
*/
|
||||
static inline SessionContext Init(storage::Config &storage_config, query::InterpreterConfig &interp_config,
|
||||
utils::Synchronized<auth::Auth, utils::WritePrioritizedRWLock> *auth,
|
||||
query::AuthQueryHandler *auth_handler, query::AuthChecker *auth_checker) {
|
||||
MG_ASSERT(auth, "Passed a nullptr auth");
|
||||
MG_ASSERT(auth_handler, "Passed a nullptr auth_handler");
|
||||
MG_ASSERT(auth_checker, "Passed a nullptr auth_checker");
|
||||
|
||||
storage_config.name = kDefaultDB;
|
||||
auto interp_context = std::make_shared<query::InterpreterContext>(
|
||||
storage_config, interp_config, storage_config.durability.storage_directory, auth_handler, auth_checker);
|
||||
MG_ASSERT(interp_context, "Failed to construct main interpret context.");
|
||||
|
||||
return SessionContext{interp_context, utils::GenerateUUID(), auth};
|
||||
}
|
||||
#endif
|
||||
|
||||
} // namespace memgraph::dbms
|
||||
4
src/distributed/CMakeLists.txt
Normal file
4
src/distributed/CMakeLists.txt
Normal file
@@ -0,0 +1,4 @@
|
||||
add_library(mg-distributed)
|
||||
add_library(mg::distributed ALIAS mg-distributed)
|
||||
target_include_directories(mg-distributed PUBLIC include )
|
||||
target_sources(mg-distributed PRIVATE lamport_clock.cpp)
|
||||
61
src/distributed/include/distributed/lamport_clock.hpp
Normal file
61
src/distributed/include/distributed/lamport_clock.hpp
Normal file
@@ -0,0 +1,61 @@
|
||||
// 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 <atomic>
|
||||
#include <compare>
|
||||
#include <cstdint>
|
||||
#include <numeric>
|
||||
|
||||
namespace memgraph::distributed {
|
||||
|
||||
// forward declare, for strong timestamps
|
||||
template <typename Tag>
|
||||
struct LamportClock;
|
||||
|
||||
template <typename Tag>
|
||||
struct timestamp {
|
||||
friend std::strong_ordering operator<=>(timestamp const &, timestamp const &) = default;
|
||||
|
||||
private:
|
||||
friend struct LamportClock<Tag>;
|
||||
|
||||
explicit timestamp(uint64_t value) : value_{value} {}
|
||||
uint64_t value_;
|
||||
};
|
||||
|
||||
constexpr struct internal_t {
|
||||
} internal;
|
||||
constexpr struct send_t {
|
||||
} send;
|
||||
constexpr struct receive_t {
|
||||
} receive;
|
||||
|
||||
template <typename Tag>
|
||||
struct LamportClock {
|
||||
using timestamp_t = timestamp<Tag>;
|
||||
|
||||
auto get_timestamp(internal_t) -> timestamp_t { return timestamp_t{++internal}; };
|
||||
auto get_timestamp(send_t) -> timestamp_t { return timestamp_t{++internal}; };
|
||||
auto get_timestamp(receive_t, timestamp_t received_timestamp) -> timestamp_t {
|
||||
while (true) {
|
||||
auto local_current = internal.load(std::memory_order_acquire);
|
||||
auto next = std::max(received_timestamp.value_, local_current) + 1;
|
||||
bool res = internal.compare_exchange_weak(local_current, next, std::memory_order_acq_rel);
|
||||
if (res) return timestamp_t{next};
|
||||
}
|
||||
};
|
||||
|
||||
private:
|
||||
std::atomic<uint64_t> internal = 0;
|
||||
};
|
||||
|
||||
} // namespace memgraph::distributed
|
||||
11
src/distributed/lamport_clock.cpp
Normal file
11
src/distributed/lamport_clock.cpp
Normal file
@@ -0,0 +1,11 @@
|
||||
// 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.
|
||||
#include "distributed/lamport_clock.hpp"
|
||||
10
src/flags/CMakeLists.txt
Normal file
10
src/flags/CMakeLists.txt
Normal file
@@ -0,0 +1,10 @@
|
||||
add_library(mg-flags STATIC audit.cpp
|
||||
bolt.cpp
|
||||
general.cpp
|
||||
isolation_level.cpp
|
||||
log_level.cpp
|
||||
memory_limit.cpp
|
||||
run_time_configurable.cpp
|
||||
storage_mode.cpp)
|
||||
target_include_directories(mg-flags PUBLIC ${CMAKE_SOURCE_DIR}/include)
|
||||
target_link_libraries(mg-flags PUBLIC spdlog::spdlog mg-settings mg-utils)
|
||||
20
src/flags/all.hpp
Normal file
20
src/flags/all.hpp
Normal file
@@ -0,0 +1,20 @@
|
||||
// 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 "flags/audit.hpp"
|
||||
#include "flags/bolt.hpp"
|
||||
#include "flags/general.hpp"
|
||||
#include "flags/isolation_level.hpp"
|
||||
#include "flags/log_level.hpp"
|
||||
#include "flags/memory_limit.hpp"
|
||||
#include "flags/run_time_configurable.hpp"
|
||||
#include "flags/storage_mode.hpp"
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user