Compare commits

..

10 Commits

Author SHA1 Message Date
Antonio Andelic
c8769fa677 Merge branch 'MG-pmr-property-value' into MG-pmr-property-value-fixed 2022-02-11 12:43:29 +01:00
Antonio Andelic
16245d7ec8 Fix tests 2022-02-11 12:42:40 +01:00
Antonio Andelic
0feeae443c Merge branch 'T0515-MG-fixed-size-pool-resource' into MG-pmr-property-value-fixed 2022-02-11 11:33:03 +01:00
Antonio Andelic
5338ef5750 Merge branch 'master' into T0515-MG-fixed-size-pool-resource 2022-02-11 11:32:50 +01:00
Antonio Andelic
49ad114366 PMR property value 2022-02-11 11:32:11 +01:00
Antonio Andelic
77c8a650fa Merge branch 'master' into T0515-MG-fixed-size-pool-resource 2021-10-28 12:58:04 +02:00
Antonio Andelic
e27485388d Use FixedSizePool 2021-06-17 11:39:30 +02:00
Antonio Andelic
51b5d81018 Merge branch 'master' into T0515-MG-fixed-size-pool-resource 2021-06-17 11:36:32 +02:00
Antonio Andelic
10cc0c01d2 Add tests for FixedSizePoolResource 2021-03-22 14:06:00 +01:00
Antonio Andelic
45cd78a435 Add FixedSizePoolResource PoC 2021-03-22 14:05:47 +01:00
670 changed files with 15989 additions and 23979 deletions

View File

@@ -1,7 +1,6 @@
--- ---
Checks: '*, Checks: '*,
-abseil-string-find-str-contains, -abseil-string-find-str-contains,
-altera-id-dependent-backward-branch,
-altera-struct-pack-align, -altera-struct-pack-align,
-altera-unroll-loops, -altera-unroll-loops,
-android-*, -android-*,
@@ -61,9 +60,7 @@ Checks: '*,
-readability-magic-numbers, -readability-magic-numbers,
-readability-named-parameter, -readability-named-parameter,
-misc-no-recursion, -misc-no-recursion,
-concurrency-mt-unsafe, -concurrency-mt-unsafe'
-bugprone-easily-swappable-parameters'
WarningsAsErrors: '' WarningsAsErrors: ''
HeaderFilterRegex: 'src/.*' HeaderFilterRegex: 'src/.*'
AnalyzeTemporaryDtors: false AnalyzeTemporaryDtors: false
@@ -90,3 +87,4 @@ CheckOptions:
- key: modernize-use-nullptr.NullMacros - key: modernize-use-nullptr.NullMacros
value: 'NULL' value: 'NULL'
... ...

View File

@@ -16,7 +16,6 @@ tmpdir=$(mktemp -d repo-XXXXXXXX)
trap "rm -rf $tmpdir" EXIT INT trap "rm -rf $tmpdir" EXIT INT
modified_files=$(git diff --cached --name-only --diff-filter=AM $against | sed -nE "/.*\.(cpp|cc|cxx|c|h|hpp)$/p") modified_files=$(git diff --cached --name-only --diff-filter=AM $against | sed -nE "/.*\.(cpp|cc|cxx|c|h|hpp)$/p")
FAIL=0
for file in $modified_files; do for file in $modified_files; do
echo "Checking $file..." echo "Checking $file..."
@@ -24,13 +23,21 @@ for file in $modified_files; do
git checkout-index --prefix="$tmpdir/" -- $file git checkout-index --prefix="$tmpdir/" -- $file
# Do not break header checker echo "Running clang-format..."
$project_folder/tools/git-clang-format $tmpdir/$file
code=$?
if [ $code -ne 0 ]; then
break
fi
echo "Running header checker..." echo "Running header checker..."
$project_folder/tools/header-checker.py $tmpdir/$file $file --amend-year $project_folder/tools/header-checker.py $tmpdir/$file $file --amend-year
CODE=$? code=$?
if [ $CODE -ne 0 ]; then
FAIL=1 if [ $code -ne 0 ]; then
break
fi fi
done; done;
return ${FAIL} return $code

View File

@@ -1,7 +1,4 @@
name: Diff name: Diff
concurrency:
group: ${{ github.head_ref || github.sha }}
cancel-in-progress: true
on: on:
push: push:
@@ -115,7 +112,7 @@ jobs:
source /opt/toolchain-v4/activate source /opt/toolchain-v4/activate
# Restrict clang-tidy results only to the modified parts # Restrict clang-tidy results only to the modified parts
git diff -U0 master... -- src | ./tools/github/clang-tidy/clang-tidy-diff.py -p 1 -j $THREADS -path build | tee ./build/clang_tidy_output.txt git diff -U0 master... -- src ':!*.hpp' | ./tools/github/clang-tidy/clang-tidy-diff.py -p 1 -j $THREADS -path build | tee ./build/clang_tidy_output.txt
# Fail if any warning is reported # Fail if any warning is reported
! cat ./build/clang_tidy_output.txt | ./tools/github/clang-tidy/grep_error_lines.sh > /dev/null ! cat ./build/clang_tidy_output.txt | ./tools/github/clang-tidy/grep_error_lines.sh > /dev/null

View File

@@ -6,11 +6,11 @@ on: workflow_dispatch
jobs: jobs:
centos-7: centos-7:
runs-on: [self-hosted, DockerMgBuild, X64] runs-on: [self-hosted, DockerMgBuild]
timeout-minutes: 60 timeout-minutes: 60
steps: steps:
- name: "Set up repository" - name: "Set up repository"
uses: actions/checkout@v3 uses: actions/checkout@v2
with: with:
fetch-depth: 0 # Required because of release/get_version.py fetch-depth: 0 # Required because of release/get_version.py
- name: "Build package" - name: "Build package"
@@ -22,29 +22,29 @@ jobs:
name: centos-7 name: centos-7
path: build/output/centos-7/memgraph*.rpm path: build/output/centos-7/memgraph*.rpm
centos-9: centos-8:
runs-on: [self-hosted, DockerMgBuild, X64] runs-on: [self-hosted, DockerMgBuild]
timeout-minutes: 60 timeout-minutes: 60
steps: steps:
- name: "Set up repository" - name: "Set up repository"
uses: actions/checkout@v3 uses: actions/checkout@v2
with: with:
fetch-depth: 0 # Required because of release/get_version.py fetch-depth: 0 # Required because of release/get_version.py
- name: "Build package" - name: "Build package"
run: | run: |
./release/package/run.sh package centos-9 ./release/package/run.sh package centos-8
- name: "Upload package" - name: "Upload package"
uses: actions/upload-artifact@v2 uses: actions/upload-artifact@v2
with: with:
name: centos-9 name: centos-8
path: build/output/centos-9/memgraph*.rpm path: build/output/centos-8/memgraph*.rpm
debian-10: debian-10:
runs-on: [self-hosted, DockerMgBuild, X64] runs-on: [self-hosted, DockerMgBuild]
timeout-minutes: 60 timeout-minutes: 60
steps: steps:
- name: "Set up repository" - name: "Set up repository"
uses: actions/checkout@v3 uses: actions/checkout@v2
with: with:
fetch-depth: 0 # Required because of release/get_version.py fetch-depth: 0 # Required because of release/get_version.py
- name: "Build package" - name: "Build package"
@@ -57,11 +57,11 @@ jobs:
path: build/output/debian-10/memgraph*.deb path: build/output/debian-10/memgraph*.deb
debian-11: debian-11:
runs-on: [self-hosted, DockerMgBuild, X64] runs-on: [self-hosted, DockerMgBuild]
timeout-minutes: 60 timeout-minutes: 60
steps: steps:
- name: "Set up repository" - name: "Set up repository"
uses: actions/checkout@v3 uses: actions/checkout@v2
with: with:
fetch-depth: 0 # Required because of release/get_version.py fetch-depth: 0 # Required because of release/get_version.py
- name: "Build package" - name: "Build package"
@@ -74,11 +74,11 @@ jobs:
path: build/output/debian-11/memgraph*.deb path: build/output/debian-11/memgraph*.deb
docker: docker:
runs-on: [self-hosted, DockerMgBuild, X64] runs-on: [self-hosted, DockerMgBuild]
timeout-minutes: 60 timeout-minutes: 60
steps: steps:
- name: "Set up repository" - name: "Set up repository"
uses: actions/checkout@v3 uses: actions/checkout@v2
with: with:
fetch-depth: 0 # Required because of release/get_version.py fetch-depth: 0 # Required because of release/get_version.py
- name: "Build package" - name: "Build package"
@@ -93,11 +93,11 @@ jobs:
path: build/output/docker/memgraph*.tar.gz path: build/output/docker/memgraph*.tar.gz
ubuntu-1804: ubuntu-1804:
runs-on: [self-hosted, DockerMgBuild, X64] runs-on: [self-hosted, DockerMgBuild]
timeout-minutes: 60 timeout-minutes: 60
steps: steps:
- name: "Set up repository" - name: "Set up repository"
uses: actions/checkout@v3 uses: actions/checkout@v2
with: with:
fetch-depth: 0 # Required because of release/get_version.py fetch-depth: 0 # Required because of release/get_version.py
- name: "Build package" - name: "Build package"
@@ -110,11 +110,11 @@ jobs:
path: build/output/ubuntu-18.04/memgraph*.deb path: build/output/ubuntu-18.04/memgraph*.deb
ubuntu-2004: ubuntu-2004:
runs-on: [self-hosted, DockerMgBuild, X64] runs-on: [self-hosted, DockerMgBuild]
timeout-minutes: 60 timeout-minutes: 60
steps: steps:
- name: "Set up repository" - name: "Set up repository"
uses: actions/checkout@v3 uses: actions/checkout@v2
with: with:
fetch-depth: 0 # Required because of release/get_version.py fetch-depth: 0 # Required because of release/get_version.py
- name: "Build package" - name: "Build package"
@@ -126,29 +126,12 @@ jobs:
name: ubuntu-2004 name: ubuntu-2004
path: build/output/ubuntu-20.04/memgraph*.deb path: build/output/ubuntu-20.04/memgraph*.deb
ubuntu-2204:
runs-on: [self-hosted, DockerMgBuild, X64]
timeout-minutes: 60
steps:
- name: "Set up repository"
uses: actions/checkout@v3
with:
fetch-depth: 0 # Required because of release/get_version.py
- name: "Build package"
run: |
./release/package/run.sh package ubuntu-22.04
- name: "Upload package"
uses: actions/upload-artifact@v2
with:
name: ubuntu-2204
path: build/output/ubuntu-22.04/memgraph*.deb
debian-11-platform: debian-11-platform:
runs-on: [self-hosted, DockerMgBuild, X64] runs-on: [self-hosted, DockerMgBuild]
timeout-minutes: 60 timeout-minutes: 60
steps: steps:
- name: "Set up repository" - name: "Set up repository"
uses: actions/checkout@v3 uses: actions/checkout@v2
with: with:
fetch-depth: 0 # Required because of release/get_version.py fetch-depth: 0 # Required because of release/get_version.py
- name: "Build package" - name: "Build package"
@@ -159,20 +142,3 @@ jobs:
with: with:
name: debian-11-platform name: debian-11-platform
path: build/output/debian-11/memgraph*.deb path: build/output/debian-11/memgraph*.deb
debian-11-arm:
runs-on: [self-hosted, DockerMgBuild, ARM64, strange]
timeout-minutes: 60
steps:
- name: "Set up repository"
uses: actions/checkout@v3
with:
fetch-depth: 0 # Required because of release/get_version.py
- name: "Build package"
run: |
./release/package/run.sh package debian-11-arm
- name: "Upload package"
uses: actions/upload-artifact@v2
with:
name: debian-11
path: build/output/debian-11/memgraph*.deb

View File

@@ -1,49 +0,0 @@
name: Publish Docker images
on:
workflow_dispatch:
inputs:
version:
description: "Memgraph binary version to publish on Dockerhub."
required: true
jobs:
docker_publish:
runs-on: ubuntu-latest
env:
DOCKER_ORGANIZATION_NAME: memgraph
DOCKER_REPOSITORY_NAME: memgraph
steps:
- name: Checkout
uses: actions/checkout@v2
- name: Set up QEMU
uses: docker/setup-qemu-action@v1
- name: Set up Docker Buildx
id: buildx
uses: docker/setup-buildx-action@v1
- name: Log in to Docker Hub
uses: docker/login-action@v1
with:
username: ${{ secrets.DOCKER_USERNAME }}
password: ${{ secrets.DOCKER_PASSWORD }}
- name: Download memgraph binary
run: |
cd release/docker
curl -L https://download.memgraph.com/memgraph/v${{ github.event.inputs.version }}/debian-11/memgraph_${{ github.event.inputs.version }}-1_amd64.deb > memgraph-amd64.deb
curl -L https://download.memgraph.com/memgraph/v${{ github.event.inputs.version }}/debian-11-aarch64/memgraph_${{ github.event.inputs.version }}-1_arm64.deb > memgraph-arm64.deb
- name: Build & push docker images
run: |
cd release/docker
docker buildx build \
--build-arg BINARY_NAME="memgraph-" \
--build-arg EXTENSION="deb" \
--platform linux/amd64,linux/arm64 \
--tag $DOCKER_ORGANIZATION_NAME/$DOCKER_REPOSITORY_NAME:${{ github.event.inputs.version }} \
--tag $DOCKER_ORGANIZATION_NAME/$DOCKER_REPOSITORY_NAME:latest \
--file memgraph_deb.dockerfile \
--push .

2
.gitignore vendored
View File

@@ -9,7 +9,6 @@
*.swn *.swn
*.swo *.swo
*.swp *.swp
*~ *~
.DS_Store .DS_Store
.gdb_history .gdb_history
@@ -27,7 +26,6 @@ src/query/frontend/opencypher/generated/
tags tags
ve/ ve/
ve3/ ve3/
.cache/
perf.data* perf.data*
TAGS TAGS
*.apollo_measurements *.apollo_measurements

View File

@@ -1,24 +0,0 @@
repos:
- repo: https://github.com/pre-commit/pre-commit-hooks
rev: v2.3.0
hooks:
- id: check-yaml
- id: end-of-file-fixer
- id: trailing-whitespace
- repo: https://github.com/psf/black
rev: 22.3.0
hooks:
- id: black
args: # arguments to configure black
- --line-length=120
- --include='\.pyi?$'
# these folders wont be formatted by black
- --exclude="""\.git |
\.__pycache__|
build|
libs|
.cache"""
- repo: https://github.com/pre-commit/mirrors-clang-format
rev: v13.0.0
hooks:
- id: clang-format

View File

@@ -184,8 +184,7 @@ set(CMAKE_CXX_STANDARD_REQUIRED ON)
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wall \ set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wall \
-Werror=switch -Werror=switch-bool -Werror=return-type \ -Werror=switch -Werror=switch-bool -Werror=return-type \
-Werror=return-stack-address \ -Werror=return-stack-address \
-Wno-c99-designator \ -Wno-c99-designator")
-DBOOST_ASIO_USE_TS_EXECUTOR_AS_DEFAULT")
# Don't omit frame pointer in RelWithDebInfo, for additional callchain debug. # Don't omit frame pointer in RelWithDebInfo, for additional callchain debug.
set(CMAKE_CXX_FLAGS_RELWITHDEBINFO set(CMAKE_CXX_FLAGS_RELWITHDEBINFO
@@ -205,8 +204,6 @@ set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -fuse-ld=gold")
# release flags # release flags
set(CMAKE_CXX_FLAGS_RELEASE "-O2 -DNDEBUG") set(CMAKE_CXX_FLAGS_RELEASE "-O2 -DNDEBUG")
SET(CMAKE_CXX_LINK_FLAGS "${CMAKE_CXX_LINK_FLAGS} -pthread")
#debug flags #debug flags
set(PREFERRED_DEBUGGER "gdb" CACHE STRING set(PREFERRED_DEBUGGER "gdb" CACHE STRING
"Tunes the debug output for your preferred debugger (gdb or lldb).") "Tunes the debug output for your preferred debugger (gdb or lldb).")

View File

@@ -1 +1 @@
* @antaljanosbenjamin @kostasrim * @gitbuda @antonio2368 @antaljanosbenjamin @kostasrim @jbajic

View File

@@ -54,18 +54,6 @@ Memgraph is implemented in C/C++ and leverages an in-memory first architecture
to ensure that youre getting the best possible performance consistently and to ensure that youre getting the best possible performance consistently and
without surprises. Its also ACID-compliant and highly available. without surprises. Its also ACID-compliant and highly available.
## :video_game: Memgraph Playground
You don't need to install anything to try out Memgraph. Check out
our **[Memgraph Playground](https://playground.memgraph.com/)** sandboxes in
your browser.
<p align="left">
<a href="https://playground.memgraph.com/">
<img width="450px" alt="Memgraph Playground" src="https://download.memgraph.com/asset/github/memgraph/memgraph-playground.png">
</a>
</p>
## :floppy_disk: Download & Install ## :floppy_disk: Download & Install
### Windows ### Windows

View File

@@ -47,14 +47,6 @@ modifications:
value: "" value: ""
override: false override: false
- name: "bolt_cert_file"
value: "/etc/memgraph/ssl/cert.pem"
override: false
- name: "bolt_key_file"
value: "/etc/memgraph/ssl/key.pem"
override: false
- name: "storage_properties_on_edges" - name: "storage_properties_on_edges"
value: "true" value: "true"
override: true override: true

View File

@@ -18,16 +18,14 @@ WIDTH = 80
def wrap_text(s, initial_indent="# "): def wrap_text(s, initial_indent="# "):
return "\n#\n".join( return "\n#\n".join(
map( map(lambda x: textwrap.fill(x, WIDTH, initial_indent=initial_indent,
lambda x: textwrap.fill(x, WIDTH, initial_indent=initial_indent, subsequent_indent="# "), subsequent_indent="# "), s.split("\n")))
s.split("\n"),
)
)
def extract_flags(binary_path): def extract_flags(binary_path):
ret = {} ret = {}
data = subprocess.run([binary_path, "--help-xml"], stdout=subprocess.PIPE).stdout.decode("utf-8") data = subprocess.run([binary_path, "--help-xml"],
stdout=subprocess.PIPE).stdout.decode("utf-8")
root = ET.fromstring(data) root = ET.fromstring(data)
for child in root: for child in root:
if child.tag == "usage" and child.text.lower().count("warning"): if child.tag == "usage" and child.text.lower().count("warning"):
@@ -48,7 +46,8 @@ def apply_config_to_flags(config, flags):
for modification in config["modifications"]: for modification in config["modifications"]:
name = modification["name"] name = modification["name"]
if name not in flags: if name not in flags:
print("WARNING: Flag '" + name + "' missing from binary!", file=sys.stderr) print("WARNING: Flag '" + name + "' missing from binary!",
file=sys.stderr)
continue continue
flags[name]["default"] = modification["value"] flags[name]["default"] = modification["value"]
flags[name]["override"] = modification["override"] flags[name]["override"] = modification["override"]
@@ -76,9 +75,8 @@ def extract_sections(flags):
else: else:
sections.append((current_section, current_flags)) sections.append((current_section, current_flags))
sections.append(("other", other)) sections.append(("other", other))
assert set(sum(map(lambda x: x[1], sections), [])) == set( assert set(sum(map(lambda x: x[1], sections), [])) == set(flags.keys()), \
flags.keys() "The section extraction algorithm lost some flags!"
), "The section extraction algorithm lost some flags!"
return sections return sections
@@ -91,7 +89,8 @@ def generate_config_file(sections, flags):
helpstr = flag["meaning"] + " [" + flag["type"] + "]" helpstr = flag["meaning"] + " [" + flag["type"] + "]"
ret += wrap_text(helpstr) + "\n" ret += wrap_text(helpstr) + "\n"
prefix = "# " if not flag["override"] else "" prefix = "# " if not flag["override"] else ""
ret += prefix + "--" + flag["name"].replace("_", "-") + "=" + flag["default"] + "\n\n" ret += prefix + "--" + flag["name"].replace("_", "-") + \
"=" + flag["default"] + "\n\n"
ret += "\n" ret += "\n"
ret += wrap_text(config["footer"]) ret += wrap_text(config["footer"])
return ret.strip() + "\n" return ret.strip() + "\n"
@@ -99,16 +98,13 @@ def generate_config_file(sections, flags):
if __name__ == "__main__": if __name__ == "__main__":
parser = argparse.ArgumentParser() parser = argparse.ArgumentParser()
parser.add_argument("memgraph_binary", help="path to Memgraph binary") parser.add_argument("memgraph_binary",
parser.add_argument( help="path to Memgraph binary")
"output_file", parser.add_argument("output_file",
help="path where to store the generated Memgraph " "configuration file", help="path where to store the generated Memgraph "
) "configuration file")
parser.add_argument( parser.add_argument("--config-file", default=CONFIG_FILE,
"--config-file", help="path to generator configuration file")
default=CONFIG_FILE,
help="path to generator configuration file",
)
args = parser.parse_args() args = parser.parse_args()
flags = extract_flags(args.memgraph_binary) flags = extract_flags(args.memgraph_binary)

View File

@@ -11,7 +11,7 @@ TOOLCHAIN_BUILD_DEPS=(
gnupg2 # used for archive signature verification gnupg2 # used for archive signature verification
tar gzip bzip2 xz unzip # used for archive unpacking tar gzip bzip2 xz unzip # used for archive unpacking
zlib-devel # zlib library used for all builds zlib-devel # zlib library used for all builds
expat-devel libipt libipt-devel libbabeltrace-devel xz-devel python3-devel # gdb expat-devel libipt-devel libbabeltrace-devel xz-devel python3-devel # gdb
texinfo # gdb texinfo # gdb
libcurl-devel # cmake libcurl-devel # cmake
curl # snappy curl # snappy
@@ -22,7 +22,6 @@ TOOLCHAIN_BUILD_DEPS=(
openssl-devel openssl-devel
gmp-devel gmp-devel
gperf gperf
patch
) )
TOOLCHAIN_RUN_DEPS=( TOOLCHAIN_RUN_DEPS=(
@@ -106,7 +105,7 @@ install() {
https://repo.ius.io/ius-release-el7.rpm https://repo.ius.io/ius-release-el7.rpm
yum update -y yum update -y
yum install -y wget python3 python3-pip yum install -y wget python3 python3-pip
yum install -y git yum install -y git224
for pkg in $1; do for pkg in $1; do
if [ "$pkg" == libipt ]; then if [ "$pkg" == libipt ]; then
if ! yum list installed libipt >/dev/null 2>/dev/null; then if ! yum list installed libipt >/dev/null 2>/dev/null; then

159
environment/os/centos-8.sh Executable file
View File

@@ -0,0 +1,159 @@
#!/bin/bash
set -Eeuo pipefail
DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" >/dev/null 2>&1 && pwd )"
source "$DIR/../util.sh"
TOOLCHAIN_BUILD_DEPS=(
coreutils gcc gcc-c++ make # generic build tools
wget # used for archive download
gnupg2 # used for archive signature verification
tar gzip bzip2 xz unzip # used for archive unpacking
zlib-devel # zlib library used for all builds
expat-devel libipt-devel libbabeltrace-devel xz-devel python36-devel texinfo # for gdb
libcurl-devel # for cmake
curl # snappy
readline-devel # for cmake and llvm
libffi-devel libxml2-devel # for llvm
libedit-devel pcre-devel automake bison # for swig
file
openssl-devel
gmp-devel
gperf
)
TOOLCHAIN_RUN_DEPS=(
make # generic build tools
tar gzip bzip2 xz # used for archive unpacking
zlib # zlib library used for all builds
expat libipt libbabeltrace xz-libs python36 # for gdb
readline # for cmake and llvm
libffi libxml2 # for llvm
openssl-devel
)
MEMGRAPH_BUILD_DEPS=(
git # source code control
make pkgconf-pkg-config # build system
curl wget # for downloading libs
libuuid-devel java-11-openjdk # required by antlr
readline-devel # for memgraph console
python36-devel # for query modules
openssl-devel
libseccomp-devel
python36 python3-virtualenv python3-pip nmap-ncat # for qa, macro_benchmark and stress tests
#
# IMPORTANT: python3-yaml does NOT exist on CentOS
# Install it manually using `pip3 install PyYAML`
#
PyYAML # Package name here does not correspond to the yum package!
libcurl-devel # mg-requests
rpm-build rpmlint # for RPM package building
doxygen graphviz # source documentation generators
which mono-complete dotnet-sdk-3.1 nodejs golang zip unzip java-11-openjdk-devel # for driver tests
sbcl # for custom Lisp C++ preprocessing
autoconf # for jemalloc code generation
libtool # for protobuf code generation
)
list() {
echo "$1"
}
check() {
local missing=""
for pkg in $1; do
if [ "$pkg" == "PyYAML" ]; then
if ! python3 -c "import yaml" >/dev/null 2>/dev/null; then
missing="$pkg $missing"
fi
continue
fi
if ! yum list installed "$pkg" >/dev/null 2>/dev/null; then
missing="$pkg $missing"
fi
done
if [ "$missing" != "" ]; then
echo "MISSING PACKAGES: $missing"
exit 1
fi
}
install() {
cd "$DIR"
if [ "$EUID" -ne 0 ]; then
echo "Please run as root."
exit 1
fi
# If GitHub Actions runner is installed, append LANG to the environment.
# Python related tests doesn't work the LANG export.
if [ -d "/home/gh/actions-runner" ]; then
echo "LANG=en_US.utf8" >> /home/gh/actions-runner/.env
else
echo "NOTE: export LANG=en_US.utf8"
fi
dnf install -y epel-release
dnf install -y 'dnf-command(config-manager)'
dnf config-manager --set-enabled powertools # Required to install texinfo.
dnf update -y
dnf install -y wget git python36 python3-pip
for pkg in $1; do
if [ "$pkg" == libipt ]; then
if ! dnf list installed libipt >/dev/null 2>/dev/null; then
dnf install -y http://repo.okay.com.mx/centos/8/x86_64/release/libipt-1.6.1-8.el8.x86_64.rpm
fi
continue
fi
if [ "$pkg" == libipt-devel ]; then
if ! yum list installed libipt-devel >/dev/null 2>/dev/null; then
dnf install -y http://repo.okay.com.mx/centos/8/x86_64/release/libipt-devel-1.6.1-8.el8.x86_64.rpm
fi
continue
fi
# Install GDB dependencies not present in the standard repos.
# https://bugs.centos.org/view.php?id=17068
# https://centos.pkgs.org
# Since 2020, there is Babeltrace2 (https://babeltrace.org). Not used
# within GDB yet (an assumption).
if [ "$pkg" == libbabeltrace-devel ]; then
if ! dnf list installed libbabeltrace-devel >/dev/null 2>/dev/null; then
dnf install -y http://mirror.centos.org/centos/8/PowerTools/x86_64/os/Packages/libbabeltrace-devel-1.5.4-3.el8.x86_64.rpm
fi
continue
fi
if [ "$pkg" == sbcl ]; then
if ! dnf list installed cl-asdf >/dev/null 2>/dev/null; then
dnf install -y https://pkgs.dyn.su/el8/base/x86_64/cl-asdf-20101028-18.el8.noarch.rpm
fi
if ! dnf list installed common-lisp-controller >/dev/null 2>/dev/null; then
dnf install -y https://pkgs.dyn.su/el8/base/x86_64/common-lisp-controller-7.4-20.el8.noarch.rpm
fi
if ! dnf list installed sbcl >/dev/null 2>/dev/null; then
dnf install -y https://pkgs.dyn.su/el8/base/x86_64/sbcl-2.0.1-4.el8.x86_64.rpm
fi
continue
fi
if [ "$pkg" == dotnet-sdk-3.1 ]; then
if ! dnf list installed dotnet-sdk-3.1 >/dev/null 2>/dev/null; then
wget -nv https://packages.microsoft.com/config/centos/8/packages-microsoft-prod.rpm -O packages-microsoft-prod.rpm
rpm -Uvh https://packages.microsoft.com/config/centos/8/packages-microsoft-prod.rpm
dnf update -y
dnf install -y dotnet-sdk-3.1
fi
continue
fi
if [ "$pkg" == PyYAML ]; then
if [ -z ${SUDO_USER+x} ]; then # Running as root (e.g. Docker).
pip3 install --user PyYAML
else # Running using sudo.
sudo -H -u "$SUDO_USER" bash -c "pip3 install --user PyYAML"
fi
continue
fi
dnf install -y "$pkg"
done
}
deps=$2"[*]"
"$1" "${!deps}"

View File

@@ -6,12 +6,14 @@ DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" >/dev/null 2>&1 && pwd )"
source "$DIR/../util.sh" source "$DIR/../util.sh"
TOOLCHAIN_BUILD_DEPS=( TOOLCHAIN_BUILD_DEPS=(
coreutils-common gcc gcc-c++ make # generic build tools coreutils gcc gcc-c++ make # generic build tools
wget # used for archive download wget # used for archive download
gnupg2 # used for archive signature verification gnupg2 # used for archive signature verification
tar gzip bzip2 xz unzip # used for archive unpacking tar gzip bzip2 xz unzip # used for archive unpacking
zlib-devel # zlib library used for all builds zlib-devel # zlib library used for all builds
expat-devel xz-devel python3-devel texinfo libbabeltrace-devel # for gdb expat-devel xz-devel python3-devel texinfo # for gdb
libcurl-devel # for cmake
curl # snappy
readline-devel # for cmake and llvm readline-devel # for cmake and llvm
libffi-devel libxml2-devel # for llvm libffi-devel libxml2-devel # for llvm
libedit-devel pcre-devel automake bison # for swig libedit-devel pcre-devel automake bison # for swig
@@ -19,9 +21,6 @@ TOOLCHAIN_BUILD_DEPS=(
openssl-devel openssl-devel
gmp-devel gmp-devel
gperf gperf
diffutils
libipt libipt-devel # intel
patch
) )
TOOLCHAIN_RUN_DEPS=( TOOLCHAIN_RUN_DEPS=(
@@ -32,19 +31,18 @@ TOOLCHAIN_RUN_DEPS=(
readline # for cmake and llvm readline # for cmake and llvm
libffi libxml2 # for llvm libffi libxml2 # for llvm
openssl-devel openssl-devel
perl # for openssl
) )
MEMGRAPH_BUILD_DEPS=( MEMGRAPH_BUILD_DEPS=(
git # source code control git # source code control
make pkgconf-pkg-config # build system make pkgconf-pkg-config # build system
wget # for downloading libs curl wget # for downloading libs
libuuid-devel java-11-openjdk # required by antlr libuuid-devel java-11-openjdk # required by antlr
readline-devel # for memgraph console readline-devel # for memgraph console
python3-devel # for query modules python3-devel # for query modules
openssl-devel openssl-devel
libseccomp-devel libseccomp-devel
python3 python3-pip python3-virtualenv nmap-ncat # for qa, macro_benchmark and stress tests python3 python3-virtualenv python3-pip nmap-ncat # for qa, macro_benchmark and stress tests
# #
# IMPORTANT: python3-yaml does NOT exist on CentOS # IMPORTANT: python3-yaml does NOT exist on CentOS
# Install it manually using `pip3 install PyYAML` # Install it manually using `pip3 install PyYAML`
@@ -75,6 +73,12 @@ check() {
if [ "$pkg" == "python3-virtualenv" ]; then if [ "$pkg" == "python3-virtualenv" ]; then
continue continue
fi fi
if [ "$pkg" == sbcl ]; then
if ! sbcl --version &> /dev/null; then
missing="$pkg $missing"
fi
continue
fi
if ! yum list installed "$pkg" >/dev/null 2>/dev/null; then if ! yum list installed "$pkg" >/dev/null 2>/dev/null; then
missing="$pkg $missing" missing="$pkg $missing"
fi fi
@@ -101,37 +105,13 @@ install() {
yum update -y yum update -y
yum install -y wget git python3 python3-pip yum install -y wget git python3 python3-pip
for pkg in $1; do for pkg in $1; do
# Since there is no support for libipt-devel for CentOS 9 we install
# Fedoras version of same libs, they are the same version but released
# for different OS
# TODO Update when libipt-devel releases for CentOS 9
if [ "$pkg" == libipt ]; then
if ! dnf list installed libipt >/dev/null 2>/dev/null; then
dnf install -y http://repo.okay.com.mx/centos/8/x86_64/release/libipt-1.6.1-8.el8.x86_64.rpm
fi
continue
fi
if [ "$pkg" == libipt-devel ]; then
if ! dnf list installed libipt-devel >/dev/null 2>/dev/null; then
dnf install -y http://repo.okay.com.mx/centos/8/x86_64/release/libipt-devel-1.6.1-8.el8.x86_64.rpm
fi
continue
fi
if [ "$pkg" == libbabeltrace-devel ]; then
if ! dnf list installed libbabeltrace-devel >/dev/null 2>/dev/null; then
dnf install -y http://mirror.stream.centos.org/9-stream/CRB/x86_64/os/Packages/libbabeltrace-devel-1.5.8-10.el9.x86_64.rpm
fi
continue
fi
if [ "$pkg" == sbcl ]; then if [ "$pkg" == sbcl ]; then
if ! dnf list installed cl-asdf >/dev/null 2>/dev/null; then if ! sbcl --version &> /dev/null; then
dnf install -y https://pkgs.dyn.su/el8/base/x86_64/cl-asdf-20101028-18.el8.noarch.rpm curl -s https://altushost-swe.dl.sourceforge.net/project/sbcl/sbcl/1.4.2/sbcl-1.4.2-arm64-linux-binary.tar.bz2 -o /tmp/sbcl-arm64.tar.bz2
fi tar xvjf /tmp/sbcl-arm64.tar.bz2 -C /tmp
if ! dnf list installed common-lisp-controller >/dev/null 2>/dev/null; then pushd /tmp/sbcl-1.4.2-arm64-linux
dnf install -y https://pkgs.dyn.su/el8/base/x86_64/common-lisp-controller-7.4-20.el8.noarch.rpm INSTALL_ROOT=/usr/local sh install.sh
fi popd
if ! dnf list installed sbcl >/dev/null 2>/dev/null; then
dnf install -y https://pkgs.dyn.su/el8/base/x86_64/sbcl-2.0.1-4.el8.x86_64.rpm
fi fi
continue continue
fi fi
@@ -145,11 +125,9 @@ install() {
fi fi
if [ "$pkg" == python3-virtualenv ]; then if [ "$pkg" == python3-virtualenv ]; then
if [ -z ${SUDO_USER+x} ]; then # Running as root (e.g. Docker). if [ -z ${SUDO_USER+x} ]; then # Running as root (e.g. Docker).
pip3 install virtualenv pip3 install --user virtualenv
pip3 install virtualenvwrapper
else # Running using sudo. else # Running using sudo.
sudo -H -u "$SUDO_USER" bash -c "pip3 install virtualenv" sudo -H -u "$SUDO_USER" bash -c "pip3 install --user virtualenv"
sudo -H -u "$SUDO_USER" bash -c "pip3 install virtualenvwrapper"
fi fi
continue continue
fi fi

View File

@@ -1,95 +0,0 @@
#!/bin/bash
set -Eeuo pipefail
DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" >/dev/null 2>&1 && pwd )"
source "$DIR/../util.sh"
TOOLCHAIN_BUILD_DEPS=(
coreutils gcc g++ build-essential make # generic build tools
wget # used for archive download
gnupg # used for archive signature verification
tar gzip bzip2 xz-utils unzip # used for archive unpacking
zlib1g-dev # zlib library used for all builds
libexpat1-dev liblzma-dev python3-dev texinfo # for gdb
libcurl4-openssl-dev # for cmake
libreadline-dev # for cmake and llvm
libffi-dev libxml2-dev # for llvm
libedit-dev libpcre3-dev automake bison # for swig
curl # snappy
file # for libunwind
libssl-dev # for libevent
libgmp-dev
gperf # for proxygen
git # for fbthrift
)
TOOLCHAIN_RUN_DEPS=(
make # generic build tools
tar gzip bzip2 xz-utils # used for archive unpacking
zlib1g # zlib library used for all builds
libexpat1 liblzma5 python3 # for gdb
libcurl4 # for cmake
file # for CPack
libreadline8 # for cmake and llvm
libffi7 libxml2 # for llvm
libssl-dev # for libevent
)
MEMGRAPH_BUILD_DEPS=(
git # source code control
make pkg-config # build system
curl wget # for downloading libs
uuid-dev default-jre-headless # required by antlr
libreadline-dev # for memgraph console
libpython3-dev python3-dev # for query modules
libssl-dev
libseccomp-dev
netcat # tests are using nc to wait for memgraph
python3 virtualenv python3-virtualenv python3-pip # for qa, macro_benchmark and stress tests
python3-yaml # for the configuration generator
libcurl4-openssl-dev # mg-requests
sbcl # for custom Lisp C++ preprocessing
doxygen graphviz # source documentation generators
mono-runtime mono-mcs zip unzip default-jdk-headless # for driver tests
golang nodejs npm
autoconf # for jemalloc code generation
libtool # for protobuf code generation
)
list() {
echo "$1"
}
check() {
check_all_dpkg "$1"
}
install() {
cat >/etc/apt/sources.list <<EOF
deb http://deb.debian.org/debian bullseye main
deb-src http://deb.debian.org/debian bullseye main
deb http://deb.debian.org/debian-security/ bullseye-security main
deb-src http://deb.debian.org/debian-security/ bullseye-security main
deb http://deb.debian.org/debian bullseye-updates main
deb-src http://deb.debian.org/debian bullseye-updates main
EOF
cd "$DIR"
apt update
# If GitHub Actions runner is installed, append LANG to the environment.
# Python related tests doesn't work the LANG export.
if [ -d "/home/gh/actions-runner" ]; then
echo "LANG=en_US.utf8" >> /home/gh/actions-runner/.env
else
echo "NOTE: export LANG=en_US.utf8"
fi
apt install -y wget
for pkg in $1; do
apt install -y "$pkg"
done
}
deps=$2"[*]"
"$1" "${!deps}"

View File

@@ -87,7 +87,7 @@ EOF
fi fi
apt install -y wget apt install -y wget
for pkg in $1; do for pkg in $1; do
if [ "$pkg" == dotnet-sdk-3.1 ]; then if [ "$pkg" == dotnet-sdk-3.1 ]; then
if ! dpkg -s "$pkg" 2>/dev/null >/dev/null; then if ! dpkg -s "$pkg" 2>/dev/null >/dev/null; then
wget -nv https://packages.microsoft.com/config/debian/10/packages-microsoft-prod.deb -O packages-microsoft-prod.deb wget -nv https://packages.microsoft.com/config/debian/10/packages-microsoft-prod.deb -O packages-microsoft-prod.deb
dpkg -i packages-microsoft-prod.deb dpkg -i packages-microsoft-prod.deb

View File

@@ -1,93 +0,0 @@
#!/bin/bash
set -Eeuo pipefail
DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" >/dev/null 2>&1 && pwd )"
source "$DIR/../util.sh"
TOOLCHAIN_BUILD_DEPS=(
coreutils gcc g++ build-essential make # generic build tools
wget # used for archive download
gnupg # used for archive signature verification
tar gzip bzip2 xz-utils unzip # used for archive unpacking
zlib1g-dev # zlib library used for all builds
libexpat1-dev libipt-dev libbabeltrace-dev liblzma-dev python3-dev texinfo # for gdb
libcurl4-openssl-dev # for cmake
libreadline-dev # for cmake and llvm
libffi-dev libxml2-dev # for llvm
curl # snappy
file
git # for thrift
libgmp-dev # for gdb
gperf # for proxygen
libssl-dev
libedit-dev libpcre3-dev automake bison # for swig
)
TOOLCHAIN_RUN_DEPS=(
make # generic build tools
tar gzip bzip2 xz-utils # used for archive unpacking
zlib1g # zlib library used for all builds
libexpat1 libipt2 libbabeltrace1 liblzma5 python3 # for gdb
libcurl4 # for cmake
libreadline8 # for cmake and llvm
libffi7 libxml2 # for llvm
libssl-dev # for libevent
)
MEMGRAPH_BUILD_DEPS=(
git # source code control
make pkg-config # build system
curl wget # for downloading libs
uuid-dev default-jre-headless # required by antlr
libreadline-dev # for memgraph console
libpython3-dev python3-dev # for query modules
libssl-dev
libseccomp-dev
netcat # tests are using nc to wait for memgraph
python3 python3-virtualenv python3-pip # for qa, macro_benchmark and stress tests
python3-yaml # for the configuration generator
libcurl4-openssl-dev # mg-requests
sbcl # for custom Lisp C++ preprocessing
doxygen graphviz # source documentation generators
mono-runtime mono-mcs zip unzip default-jdk-headless # for driver tests
dotnet-sdk-6.0 golang nodejs npm
autoconf # for jemalloc code generation
libtool # for protobuf code generation
)
list() {
echo "$1"
}
check() {
check_all_dpkg "$1"
}
install() {
cd "$DIR"
apt update
# If GitHub Actions runner is installed, append LANG to the environment.
# Python related tests doesn't work the LANG export.
if [ -d "/home/gh/actions-runner" ]; then
echo "LANG=en_US.utf8" >> /home/gh/actions-runner/.env
else
echo "NOTE: export LANG=en_US.utf8"
fi
apt install -y wget
for pkg in $1; do
if [ "$pkg" == dotnet-sdk-6.0 ]; then
if ! dpkg -s dotnet-sdk-6.0 2>/dev/null >/dev/null; then
wget -nv https://packages.microsoft.com/config/ubuntu/22.04/packages-microsoft-prod.deb -O packages-microsoft-prod.deb
dpkg -i packages-microsoft-prod.deb
apt-get update
apt-get install -y apt-transport-https dotnet-sdk-6.0
fi
continue
fi
apt install -y "$pkg"
done
}
deps=$2"[*]"
"$1" "${!deps}"

View File

@@ -0,0 +1,2 @@
31d30
< add_subdirectory(logging/example)

View File

@@ -1,41 +0,0 @@
diff -ur a/folly/CMakeLists.txt b/folly/CMakeLists.txt
--- a/folly/CMakeLists.txt 2021-12-12 23:10:42.000000000 +0100
+++ b/folly/CMakeLists.txt 2022-02-03 15:19:41.349693134 +0100
@@ -28,7 +28,6 @@
)
add_subdirectory(experimental/exception_tracer)
-add_subdirectory(logging/example)
if (PYTHON_EXTENSIONS)
# Create tree of symbolic links in structure required for successful
diff -ur a/folly/experimental/exception_tracer/ExceptionTracerLib.cpp b/folly/experimental/exception_tracer/ExceptionTracerLib.cpp
--- a/folly/experimental/exception_tracer/ExceptionTracerLib.cpp 2021-12-12 23:10:42.000000000 +0100
+++ b/folly/experimental/exception_tracer/ExceptionTracerLib.cpp 2022-02-03 15:19:11.003368891 +0100
@@ -96,6 +96,7 @@
#define __builtin_unreachable()
#endif
+#if 0
namespace __cxxabiv1 {
void __cxa_throw(
@@ -154,5 +155,5 @@
}
} // namespace std
-
+#endif
#endif // defined(__GLIBCXX__)
diff -ur a/folly/Portability.h b/folly/Portability.h
--- a/folly/Portability.h 2021-12-12 23:10:42.000000000 +0100
+++ b/folly/Portability.h 2022-02-03 15:19:11.003368891 +0100
@@ -566,7 +566,7 @@
#define FOLLY_HAS_COROUTINES 0
#elif (__cpp_coroutines >= 201703L || __cpp_impl_coroutine >= 201902L) && \
(__has_include(<coroutine>) || __has_include(<experimental/coroutine>))
-#define FOLLY_HAS_COROUTINES 1
+#define FOLLY_HAS_COROUTINES 0
// This is mainly to workaround bugs triggered by LTO, when stack allocated
// variables in await_suspend end up on a coroutine frame.
#define FOLLY_CORO_AWAIT_SUSPEND_NONTRIVIAL_ATTRIBUTES FOLLY_NOINLINE

View File

@@ -0,0 +1,2 @@
24d23
< find_dependency(mvfst)

View File

@@ -1,11 +0,0 @@
diff -ur a/cmake/proxygen-config.cmake.in b/cmake/proxygen-config.cmake.in
--- a/cmake/proxygen-config.cmake.in 2021-12-13 02:37:05.000000000 +0100
+++ b/cmake/proxygen-config.cmake.in 2022-01-27 17:14:28.284810621 +0100
@@ -21,7 +21,6 @@
find_dependency(folly)
find_dependency(wangle)
find_dependency(Fizz)
-find_dependency(mvfst)
# For now, anything that depends on Proxygen has to copy its FindZstd.cmake
# and issue a `find_package(Zstd)`. Uncommenting this won't work because
# this Zstd module exposes a library called `zstd`. The right fix is

View File

@@ -0,0 +1,16 @@
55,57c55,57
< # Disable RTTI.
< string(REGEX REPLACE "/GR" "" CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS}")
< set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} /GR-")
---
> # # Disable RTTI.
> # string(REGEX REPLACE "/GR" "" CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS}")
> # set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} /GR-")
80,82c80,82
< # Disable RTTI.
< string(REGEX REPLACE "-frtti" "" CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS}")
< set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fno-rtti")
---
> # # Disable RTTI.
> # string(REGEX REPLACE "-frtti" "" CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS}")
> # set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fno-rtti")

View File

@@ -1,29 +0,0 @@
diff -ur a/CMakeLists.txt b/CMakeLists.txt
--- a/CMakeLists.txt 2021-05-05 00:53:34.000000000 +0200
+++ b/CMakeLists.txt 2022-01-27 17:18:34.758302398 +0100
@@ -52,9 +52,9 @@
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} /EHs-c-")
add_definitions(-D_HAS_EXCEPTIONS=0)
- # Disable RTTI.
- string(REGEX REPLACE "/GR" "" CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS}")
- set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} /GR-")
+ # # Disable RTTI.
+ # string(REGEX REPLACE "/GR" "" CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS}")
+ # set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} /GR-")
else(CMAKE_CXX_COMPILER_ID STREQUAL "MSVC")
# Use -Wall for clang and gcc.
if(NOT CMAKE_CXX_FLAGS MATCHES "-Wall")
@@ -77,9 +77,9 @@
string(REGEX REPLACE "-fexceptions" "" CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS}")
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fno-exceptions")
- # Disable RTTI.
- string(REGEX REPLACE "-frtti" "" CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS}")
- set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fno-rtti")
+ # # Disable RTTI.
+ # string(REGEX REPLACE "-frtti" "" CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS}")
+ # set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fno-rtti")
endif(CMAKE_CXX_COMPILER_ID STREQUAL "MSVC")
# BUILD_SHARED_LIBS is a standard CMake variable, but we declare it here to make

View File

@@ -538,8 +538,7 @@ if [ ! -f $PREFIX/bin/clang ]; then
make -j$CPUS make -j$CPUS
if [[ "$for_arm" = false ]]; then if [[ "$for_arm" = false ]]; then
make -j$CPUS check-clang # run clang test suite make -j$CPUS check-clang # run clang test suite
# ldd is not used make -j$CPUS check-lld # run lld test suite
# make -j$CPUS check-lld # run lld test suite
fi fi
make install make install
popd && popd popd && popd
@@ -675,7 +674,7 @@ PROXYGEN_SHA256=5360a8ccdfb2f5a6c7b3eed331ec7ab0e2c792d579c6fff499c85c516c11fe14
SNAPPY_SHA256=75c1fbb3d618dd3a0483bff0e26d0a92b495bbe5059c8b4f1c962b478b6e06e7 SNAPPY_SHA256=75c1fbb3d618dd3a0483bff0e26d0a92b495bbe5059c8b4f1c962b478b6e06e7
SNAPPY_VERSION=1.1.9 SNAPPY_VERSION=1.1.9
XZ_VERSION=5.2.5 # for LZMA XZ_VERSION=5.2.5 # for LZMA
ZLIB_VERSION=1.2.12 ZLIB_VERSION=1.2.11
ZSTD_VERSION=1.5.0 ZSTD_VERSION=1.5.0
WANGLE_SHA256=1002e9c32b6f4837f6a760016e3b3e22f3509880ef3eaad191c80dc92655f23f WANGLE_SHA256=1002e9c32b6f4837f6a760016e3b3e22f3509880ef3eaad191c80dc92655f23f
@@ -1030,7 +1029,7 @@ if [ ! -f $PREFIX/include/snappy.h ]; then
fi fi
tar -xzf ../archives/snappy-$SNAPPY_VERSION.tar.gz tar -xzf ../archives/snappy-$SNAPPY_VERSION.tar.gz
pushd snappy-$SNAPPY_VERSION pushd snappy-$SNAPPY_VERSION
patch -p1 < ../../snappy.patch patch CMakeLists.txt ../../snappy.diff
mkdir build mkdir build
pushd build pushd build
cmake .. $COMMON_CMAKE_FLAGS \ cmake .. $COMMON_CMAKE_FLAGS \
@@ -1072,7 +1071,7 @@ if [ ! -d $PREFIX/include/folly ]; then
mkdir folly-$FBLIBS_VERSION mkdir folly-$FBLIBS_VERSION
tar -xzf ../archives/folly-$FBLIBS_VERSION.tar.gz -C folly-$FBLIBS_VERSION tar -xzf ../archives/folly-$FBLIBS_VERSION.tar.gz -C folly-$FBLIBS_VERSION
pushd folly-$FBLIBS_VERSION pushd folly-$FBLIBS_VERSION
patch -p1 < ../../folly.patch patch folly/CMakeLists.txt ../../folly.diff
# build is used by facebook builder # build is used by facebook builder
mkdir _build mkdir _build
pushd _build pushd _build
@@ -1131,7 +1130,7 @@ if [ ! -d $PREFIX/include/proxygen ]; then
mkdir proxygen-$FBLIBS_VERSION mkdir proxygen-$FBLIBS_VERSION
tar -xzf ../archives/proxygen-$FBLIBS_VERSION.tar.gz -C proxygen-$FBLIBS_VERSION tar -xzf ../archives/proxygen-$FBLIBS_VERSION.tar.gz -C proxygen-$FBLIBS_VERSION
pushd proxygen-$FBLIBS_VERSION pushd proxygen-$FBLIBS_VERSION
patch -p1 < ../../proxygen.patch patch cmake/proxygen-config.cmake.in ../../proxygen.diff
# build is used by facebook builder # build is used by facebook builder
mkdir _build mkdir _build
pushd _build pushd _build
@@ -1178,22 +1177,7 @@ popd
# create toolchain archive # create toolchain archive
if [ ! -f $NAME-binaries-$DISTRO.tar.gz ]; then if [ ! -f $NAME-binaries-$DISTRO.tar.gz ]; then
DISTRO_FULL_NAME=${DISTRO} tar --owner=root --group=root -cpvzf $NAME-binaries-$DISTRO.tar.gz -C /opt $NAME
if [[ "${DISTRO}" == centos* ]]; then
if [[ "$for_arm" = "true" ]]; then
DISTRO_FULL_NAME="$DISTRO_FULL_NAME-aarch64"
else
DISTRO_FULL_NAME="$DISTRO_FULL_NAME-x86_64"
fi
else
if [[ "$for_arm" = "true" ]]; then
DISTRO_FULL_NAME="$DISTRO_FULL_NAME-arm64"
else
DISTRO_FULL_NAME="$DISTRO_FULL_NAME-amd64"
fi
fi
tar --owner=root --group=root -cpvzf $NAME-binaries-$DISTRO_FULL_NAME.tar.gz -C /opt $NAME
fi fi
# output final instructions # output final instructions

View File

@@ -5,10 +5,6 @@ operating_system() {
sort | cut -d '=' -f 2- | sed 's/"//g' | paste -s -d '-' sort | cut -d '=' -f 2- | sed 's/"//g' | paste -s -d '-'
} }
architecture() {
uname -m
}
check_all_yum() { check_all_yum() {
local missing="" local missing=""
for pkg in $1; do for pkg in $1; do

File diff suppressed because it is too large Load Diff

View File

@@ -40,7 +40,6 @@ class InvalidContextError(Exception):
""" """
Signals using a graph element instance outside of the registered procedure. Signals using a graph element instance outside of the registered procedure.
""" """
pass pass
@@ -48,7 +47,6 @@ class UnknownError(_mgp.UnknownError):
""" """
Signals unspecified failure. Signals unspecified failure.
""" """
pass pass
@@ -56,7 +54,6 @@ class UnableToAllocateError(_mgp.UnableToAllocateError):
""" """
Signals failed memory allocation. Signals failed memory allocation.
""" """
pass pass
@@ -64,7 +61,6 @@ class InsufficientBufferError(_mgp.InsufficientBufferError):
""" """
Signals that some buffer is not big enough. Signals that some buffer is not big enough.
""" """
pass pass
@@ -73,7 +69,6 @@ class OutOfRangeError(_mgp.OutOfRangeError):
Signals that an index-like parameter has a value that is outside its Signals that an index-like parameter has a value that is outside its
possible values. possible values.
""" """
pass pass
@@ -82,7 +77,6 @@ class LogicErrorError(_mgp.LogicErrorError):
Signals faulty logic within the program such as violating logical Signals faulty logic within the program such as violating logical
preconditions or class invariants and may be preventable. preconditions or class invariants and may be preventable.
""" """
pass pass
@@ -90,7 +84,6 @@ class DeletedObjectError(_mgp.DeletedObjectError):
""" """
Signals accessing an already deleted object. Signals accessing an already deleted object.
""" """
pass pass
@@ -98,7 +91,6 @@ class InvalidArgumentError(_mgp.InvalidArgumentError):
""" """
Signals that some of the arguments have invalid values. Signals that some of the arguments have invalid values.
""" """
pass pass
@@ -106,7 +98,6 @@ class KeyAlreadyExistsError(_mgp.KeyAlreadyExistsError):
""" """
Signals that a key already exists in a container-like object. Signals that a key already exists in a container-like object.
""" """
pass pass
@@ -114,7 +105,6 @@ class ImmutableObjectError(_mgp.ImmutableObjectError):
""" """
Signals modification of an immutable object. Signals modification of an immutable object.
""" """
pass pass
@@ -122,7 +112,6 @@ class ValueConversionError(_mgp.ValueConversionError):
""" """
Signals that the conversion failed between python and cypher values. Signals that the conversion failed between python and cypher values.
""" """
pass pass
@@ -131,14 +120,12 @@ class SerializationError(_mgp.SerializationError):
Signals serialization error caused by concurrent modifications from Signals serialization error caused by concurrent modifications from
different transactions. different transactions.
""" """
pass pass
class Label: class Label:
"""Label of a Vertex.""" """Label of a Vertex."""
__slots__ = ('_name',)
__slots__ = ("_name",)
def __init__(self, name: str): def __init__(self, name: str):
self._name = name self._name = name
@@ -158,22 +145,19 @@ class Label:
# Named property value of a Vertex or an Edge. # Named property value of a Vertex or an Edge.
# It would be better to use typing.NamedTuple with typed fields, but that is # It would be better to use typing.NamedTuple with typed fields, but that is
# not available in Python 3.5. # not available in Python 3.5.
Property = namedtuple("Property", ("name", "value")) Property = namedtuple('Property', ('name', 'value'))
class Properties: class Properties:
""" """
A collection of properties either on a Vertex or an Edge. A collection of properties either on a Vertex or an Edge.
""" """
__slots__ = ('_vertex_or_edge', '_len',)
__slots__ = (
"_vertex_or_edge",
"_len",
)
def __init__(self, vertex_or_edge): def __init__(self, vertex_or_edge):
if not isinstance(vertex_or_edge, (_mgp.Vertex, _mgp.Edge)): if not isinstance(vertex_or_edge, (_mgp.Vertex, _mgp.Edge)):
raise TypeError("Expected '_mgp.Vertex' or '_mgp.Edge', got {}".format(type(vertex_or_edge))) raise TypeError("Expected '_mgp.Vertex' or '_mgp.Edge', \
got {}".format(type(vertex_or_edge)))
self._len = None self._len = None
self._vertex_or_edge = vertex_or_edge self._vertex_or_edge = vertex_or_edge
@@ -346,8 +330,7 @@ class Properties:
class EdgeType: class EdgeType:
"""Type of an Edge.""" """Type of an Edge."""
__slots__ = ('_name',)
__slots__ = ("_name",)
def __init__(self, name): def __init__(self, name):
self._name = name self._name = name
@@ -365,7 +348,7 @@ class EdgeType:
if sys.version_info >= (3, 5, 2): if sys.version_info >= (3, 5, 2):
EdgeId = typing.NewType("EdgeId", int) EdgeId = typing.NewType('EdgeId', int)
else: else:
EdgeId = int EdgeId = int
@@ -377,12 +360,12 @@ class Edge:
a query. You should not globally store an instance of an Edge. Using an a query. You should not globally store an instance of an Edge. Using an
invalid Edge instance will raise InvalidContextError. invalid Edge instance will raise InvalidContextError.
""" """
__slots__ = ('_edge',)
__slots__ = ("_edge",)
def __init__(self, edge): def __init__(self, edge):
if not isinstance(edge, _mgp.Edge): if not isinstance(edge, _mgp.Edge):
raise TypeError("Expected '_mgp.Edge', got '{}'".format(type(edge))) raise TypeError(
"Expected '_mgp.Edge', got '{}'".format(type(edge)))
self._edge = edge self._edge = edge
def __deepcopy__(self, memo): def __deepcopy__(self, memo):
@@ -425,7 +408,7 @@ class Edge:
return EdgeType(self._edge.get_type_name()) return EdgeType(self._edge.get_type_name())
@property @property
def from_vertex(self) -> "Vertex": def from_vertex(self) -> 'Vertex':
""" """
Get the source vertex. Get the source vertex.
@@ -436,7 +419,7 @@ class Edge:
return Vertex(self._edge.from_vertex()) return Vertex(self._edge.from_vertex())
@property @property
def to_vertex(self) -> "Vertex": def to_vertex(self) -> 'Vertex':
""" """
Get the destination vertex. Get the destination vertex.
@@ -470,7 +453,7 @@ class Edge:
if sys.version_info >= (3, 5, 2): if sys.version_info >= (3, 5, 2):
VertexId = typing.NewType("VertexId", int) VertexId = typing.NewType('VertexId', int)
else: else:
VertexId = int VertexId = int
@@ -482,12 +465,12 @@ class Vertex:
in a query. You should not globally store an instance of a Vertex. Using an in a query. You should not globally store an instance of a Vertex. Using an
invalid Vertex instance will raise InvalidContextError. invalid Vertex instance will raise InvalidContextError.
""" """
__slots__ = ('_vertex',)
__slots__ = ("_vertex",)
def __init__(self, vertex): def __init__(self, vertex):
if not isinstance(vertex, _mgp.Vertex): if not isinstance(vertex, _mgp.Vertex):
raise TypeError("Expected '_mgp.Vertex', got '{}'".format(type(vertex))) raise TypeError(
"Expected '_mgp.Vertex', got '{}'".format(type(vertex)))
self._vertex = vertex self._vertex = vertex
def __deepcopy__(self, memo): def __deepcopy__(self, memo):
@@ -530,7 +513,8 @@ class Vertex:
""" """
if not self.is_valid(): if not self.is_valid():
raise InvalidContextError() raise InvalidContextError()
return tuple(Label(self._vertex.label_at(i)) for i in range(self._vertex.labels_count())) return tuple(Label(self._vertex.label_at(i))
for i in range(self._vertex.labels_count()))
def add_label(self, label: str) -> None: def add_label(self, label: str) -> None:
""" """
@@ -631,8 +615,7 @@ class Vertex:
class Path: class Path:
"""Path containing Vertex and Edge instances.""" """Path containing Vertex and Edge instances."""
__slots__ = ('_path', '_vertices', '_edges')
__slots__ = ("_path", "_vertices", "_edges")
def __init__(self, starting_vertex_or_path: typing.Union[_mgp.Path, Vertex]): def __init__(self, starting_vertex_or_path: typing.Union[_mgp.Path, Vertex]):
"""Initialize with a starting Vertex. """Initialize with a starting Vertex.
@@ -653,7 +636,8 @@ class Path:
raise InvalidContextError() raise InvalidContextError()
self._path = _mgp.Path.make_with_start(vertex) self._path = _mgp.Path.make_with_start(vertex)
else: else:
raise TypeError("Expected '_mgp.Vertex' or '_mgp.Path', got '{}'".format(type(starting_vertex_or_path))) raise TypeError("Expected '_mgp.Vertex' or '_mgp.Path', got '{}'"
.format(type(starting_vertex_or_path)))
def __copy__(self): def __copy__(self):
if not self.is_valid(): if not self.is_valid():
@@ -694,7 +678,8 @@ class Path:
extension. extension.
""" """
if not isinstance(edge, Edge): if not isinstance(edge, Edge):
raise TypeError("Expected '_mgp.Edge', got '{}'".format(type(edge))) raise TypeError(
"Expected '_mgp.Edge', got '{}'".format(type(edge)))
if not self.is_valid() or not edge.is_valid(): if not self.is_valid() or not edge.is_valid():
raise InvalidContextError() raise InvalidContextError()
self._path.expand(edge._edge) self._path.expand(edge._edge)
@@ -713,7 +698,8 @@ class Path:
raise InvalidContextError() raise InvalidContextError()
if self._vertices is None: if self._vertices is None:
num_vertices = self._path.size() + 1 num_vertices = self._path.size() + 1
self._vertices = tuple(Vertex(self._path.vertex_at(i)) for i in range(num_vertices)) self._vertices = tuple(Vertex(self._path.vertex_at(i))
for i in range(num_vertices))
return self._vertices return self._vertices
@property @property
@@ -727,14 +713,14 @@ class Path:
raise InvalidContextError() raise InvalidContextError()
if self._edges is None: if self._edges is None:
num_edges = self._path.size() num_edges = self._path.size()
self._edges = tuple(Edge(self._path.edge_at(i)) for i in range(num_edges)) self._edges = tuple(Edge(self._path.edge_at(i))
for i in range(num_edges))
return self._edges return self._edges
class Record: class Record:
"""Represents a record of resulting field values.""" """Represents a record of resulting field values."""
__slots__ = ('fields',)
__slots__ = ("fields",)
def __init__(self, **kwargs): def __init__(self, **kwargs):
"""Initialize with name=value fields in kwargs.""" """Initialize with name=value fields in kwargs."""
@@ -743,12 +729,12 @@ class Record:
class Vertices: class Vertices:
"""Iterable over vertices in a graph.""" """Iterable over vertices in a graph."""
__slots__ = ('_graph', '_len')
__slots__ = ("_graph", "_len")
def __init__(self, graph): def __init__(self, graph):
if not isinstance(graph, _mgp.Graph): if not isinstance(graph, _mgp.Graph):
raise TypeError("Expected '_mgp.Graph', got '{}'".format(type(graph))) raise TypeError(
"Expected '_mgp.Graph', got '{}'".format(type(graph)))
self._graph = graph self._graph = graph
self._len = None self._len = None
@@ -805,12 +791,12 @@ class Vertices:
class Graph: class Graph:
"""State of the graph database in current ProcCtx.""" """State of the graph database in current ProcCtx."""
__slots__ = ('_graph',)
__slots__ = ("_graph",)
def __init__(self, graph): def __init__(self, graph):
if not isinstance(graph, _mgp.Graph): if not isinstance(graph, _mgp.Graph):
raise TypeError("Expected '_mgp.Graph', got '{}'".format(type(graph))) raise TypeError(
"Expected '_mgp.Graph', got '{}'".format(type(graph)))
self._graph = graph self._graph = graph
def __deepcopy__(self, memo): def __deepcopy__(self, memo):
@@ -899,7 +885,8 @@ class Graph:
raise InvalidContextError() raise InvalidContextError()
self._graph.detach_delete_vertex(vertex._vertex) self._graph.detach_delete_vertex(vertex._vertex)
def create_edge(self, from_vertex: Vertex, to_vertex: Vertex, edge_type: EdgeType) -> None: def create_edge(self, from_vertex: Vertex, to_vertex: Vertex,
edge_type: EdgeType) -> None:
""" """
Create an edge. Create an edge.
@@ -912,7 +899,8 @@ class Graph:
""" """
if not self.is_valid(): if not self.is_valid():
raise InvalidContextError() raise InvalidContextError()
return Edge(self._graph.create_edge(from_vertex._vertex, to_vertex._vertex, edge_type.name)) return Edge(self._graph.create_edge(from_vertex._vertex,
to_vertex._vertex, edge_type.name))
def delete_edge(self, edge: Edge) -> None: def delete_edge(self, edge: Edge) -> None:
""" """
@@ -930,7 +918,6 @@ class Graph:
class AbortError(Exception): class AbortError(Exception):
"""Signals that the procedure was asked to abort its execution.""" """Signals that the procedure was asked to abort its execution."""
pass pass
@@ -940,12 +927,12 @@ class ProcCtx:
Access to a ProcCtx is only valid during a single execution of a procedure Access to a ProcCtx is only valid during a single execution of a procedure
in a query. You should not globally store a ProcCtx instance. in a query. You should not globally store a ProcCtx instance.
""" """
__slots__ = ('_graph',)
__slots__ = ("_graph",)
def __init__(self, graph): def __init__(self, graph):
if not isinstance(graph, _mgp.Graph): if not isinstance(graph, _mgp.Graph):
raise TypeError("Expected '_mgp.Graph', got '{}'".format(type(graph))) raise TypeError(
"Expected '_mgp.Graph', got '{}'".format(type(graph)))
self._graph = Graph(graph) self._graph = Graph(graph)
def is_valid(self) -> bool: def is_valid(self) -> bool:
@@ -982,7 +969,8 @@ LocalDateTime = datetime.datetime
Duration = datetime.timedelta Duration = datetime.timedelta
Any = typing.Union[bool, str, Number, Map, Path, list, Date, LocalTime, LocalDateTime, Duration] Any = typing.Union[bool, str, Number, Map, Path,
list, Date, LocalTime, LocalDateTime, Duration]
List = typing.List List = typing.List
@@ -1015,7 +1003,7 @@ def _typing_to_cypher_type(type_):
Date: _mgp.type_date(), Date: _mgp.type_date(),
LocalTime: _mgp.type_local_time(), LocalTime: _mgp.type_local_time(),
LocalDateTime: _mgp.type_local_date_time(), LocalDateTime: _mgp.type_local_date_time(),
Duration: _mgp.type_duration(), Duration: _mgp.type_duration()
} }
try: try:
return simple_types[type_] return simple_types[type_]
@@ -1033,14 +1021,14 @@ def _typing_to_cypher_type(type_):
if type(None) in type_args: if type(None) in type_args:
types = tuple(t for t in type_args if t is not type(None)) # noqa E721 types = tuple(t for t in type_args if t is not type(None)) # noqa E721
if len(types) == 1: if len(types) == 1:
(type_arg,) = types type_arg, = types
else: else:
# We cannot do typing.Union[*types], so do the equivalent # We cannot do typing.Union[*types], so do the equivalent
# with __getitem__ which does not even need arg unpacking. # with __getitem__ which does not even need arg unpacking.
type_arg = typing.Union.__getitem__(types) type_arg = typing.Union.__getitem__(types)
return _mgp.type_nullable(_typing_to_cypher_type(type_arg)) return _mgp.type_nullable(_typing_to_cypher_type(type_arg))
elif complex_type == list: elif complex_type == list:
(type_arg,) = type_args type_arg, = type_args
return _mgp.type_list(_typing_to_cypher_type(type_arg)) return _mgp.type_list(_typing_to_cypher_type(type_arg))
raise UnsupportedTypingError(type_) raise UnsupportedTypingError(type_)
else: else:
@@ -1050,17 +1038,13 @@ def _typing_to_cypher_type(type_):
# printed the same way. `typing.List[type]` is printed as such, while # printed the same way. `typing.List[type]` is printed as such, while
# `typing.Optional[type]` is printed as 'typing.Union[type, NoneType]' # `typing.Optional[type]` is printed as 'typing.Union[type, NoneType]'
def parse_type_args(type_as_str): def parse_type_args(type_as_str):
return tuple( return tuple(map(str.strip,
map( type_as_str[type_as_str.index('[') + 1: -1].split(',')))
str.strip,
type_as_str[type_as_str.index("[") + 1 : -1].split(","),
)
)
def fully_qualified_name(cls): def fully_qualified_name(cls):
if cls.__module__ is None or cls.__module__ == "builtins": if cls.__module__ is None or cls.__module__ == 'builtins':
return cls.__name__ return cls.__name__
return cls.__module__ + "." + cls.__name__ return cls.__module__ + '.' + cls.__name__
def get_simple_type(type_as_str): def get_simple_type(type_as_str):
for simple_type, cypher_type in simple_types.items(): for simple_type, cypher_type in simple_types.items():
@@ -1076,26 +1060,28 @@ def _typing_to_cypher_type(type_):
pass pass
def parse_typing(type_as_str): def parse_typing(type_as_str):
if type_as_str.startswith("typing.Union"): if type_as_str.startswith('typing.Union'):
type_args_as_str = parse_type_args(type_as_str) type_args_as_str = parse_type_args(type_as_str)
none_type_as_str = type(None).__name__ none_type_as_str = type(None).__name__
if none_type_as_str in type_args_as_str: if none_type_as_str in type_args_as_str:
types = tuple(t for t in type_args_as_str if t != none_type_as_str) types = tuple(
t for t in type_args_as_str if t != none_type_as_str)
if len(types) == 1: if len(types) == 1:
(type_arg_as_str,) = types type_arg_as_str, = types
else: else:
type_arg_as_str = "typing.Union[" + ", ".join(types) + "]" type_arg_as_str = 'typing.Union[' + \
', '.join(types) + ']'
simple_type = get_simple_type(type_arg_as_str) simple_type = get_simple_type(type_arg_as_str)
if simple_type is not None: if simple_type is not None:
return _mgp.type_nullable(simple_type) return _mgp.type_nullable(simple_type)
return _mgp.type_nullable(parse_typing(type_arg_as_str)) return _mgp.type_nullable(parse_typing(type_arg_as_str))
elif type_as_str.startswith("typing.List"): elif type_as_str.startswith('typing.List'):
type_arg_as_str = parse_type_args(type_as_str) type_arg_as_str = parse_type_args(type_as_str)
if len(type_arg_as_str) > 1: if len(type_arg_as_str) > 1:
# Nested object could be a type consisting of a list of types (e.g. mgp.Map) # Nested object could be a type consisting of a list of types (e.g. mgp.Map)
# so we need to join the parts. # so we need to join the parts.
type_arg_as_str = ", ".join(type_arg_as_str) type_arg_as_str = ', '.join(type_arg_as_str)
else: else:
type_arg_as_str = type_arg_as_str[0] type_arg_as_str = type_arg_as_str[0]
@@ -1110,11 +1096,9 @@ def _typing_to_cypher_type(type_):
# Procedure registration # Procedure registration
class Deprecated: class Deprecated:
"""Annotate a resulting Record's field as deprecated.""" """Annotate a resulting Record's field as deprecated."""
__slots__ = ('field_type',)
__slots__ = ("field_type",)
def __init__(self, type_): def __init__(self, type_):
self.field_type = type_ self.field_type = type_
@@ -1122,7 +1106,8 @@ class Deprecated:
def raise_if_does_not_meet_requirements(func: typing.Callable[..., Record]): def raise_if_does_not_meet_requirements(func: typing.Callable[..., Record]):
if not callable(func): if not callable(func):
raise TypeError("Expected a callable object, got an instance of '{}'".format(type(func))) raise TypeError("Expected a callable object, got an instance of '{}'"
.format(type(func)))
if inspect.iscoroutinefunction(func): if inspect.iscoroutinefunction(func):
raise TypeError("Callable must not be 'async def' function") raise TypeError("Callable must not be 'async def' function")
if sys.version_info >= (3, 6): if sys.version_info >= (3, 6):
@@ -1132,25 +1117,24 @@ def raise_if_does_not_meet_requirements(func: typing.Callable[..., Record]):
raise NotImplementedError("Generator functions are not supported") raise NotImplementedError("Generator functions are not supported")
def _register_proc(func: typing.Callable[..., Record], is_write: bool): def _register_proc(func: typing.Callable[..., Record],
is_write: bool):
raise_if_does_not_meet_requirements(func) raise_if_does_not_meet_requirements(func)
register_func = _mgp.Module.add_write_procedure if is_write else _mgp.Module.add_read_procedure register_func = (
_mgp.Module.add_write_procedure if is_write
else _mgp.Module.add_read_procedure)
sig = inspect.signature(func) sig = inspect.signature(func)
params = tuple(sig.parameters.values()) params = tuple(sig.parameters.values())
if params and params[0].annotation is ProcCtx: if params and params[0].annotation is ProcCtx:
@wraps(func) @wraps(func)
def wrapper(graph, args): def wrapper(graph, args):
return func(ProcCtx(graph), *args) return func(ProcCtx(graph), *args)
params = params[1:] params = params[1:]
mgp_proc = register_func(_mgp._MODULE, wrapper) mgp_proc = register_func(_mgp._MODULE, wrapper)
else: else:
@wraps(func) @wraps(func)
def wrapper(graph, args): def wrapper(graph, args):
return func(*args) return func(*args)
mgp_proc = register_func(_mgp._MODULE, wrapper) mgp_proc = register_func(_mgp._MODULE, wrapper)
for param in params: for param in params:
name = param.name name = param.name
@@ -1165,7 +1149,8 @@ def _register_proc(func: typing.Callable[..., Record], is_write: bool):
if sig.return_annotation is not sig.empty: if sig.return_annotation is not sig.empty:
record = sig.return_annotation record = sig.return_annotation
if not isinstance(record, Record): if not isinstance(record, Record):
raise TypeError("Expected '{}' to return 'mgp.Record', got '{}'".format(func.__name__, type(record))) raise TypeError("Expected '{}' to return 'mgp.Record', got '{}'"
.format(func.__name__, type(record)))
for name, type_ in record.fields.items(): for name, type_ in record.fields.items():
if isinstance(type_, Deprecated): if isinstance(type_, Deprecated):
cypher_type = _typing_to_cypher_type(type_.field_type) cypher_type = _typing_to_cypher_type(type_.field_type)
@@ -1179,15 +1164,16 @@ def read_proc(func: typing.Callable[..., Record]):
""" """
Register `func` as a read-only procedure of the current module. Register `func` as a read-only procedure of the current module.
The decorator `read_proc` is meant to be used to register module procedures. `read_proc` is meant to be used as a decorator function to register module
The registered `func` needs to be a callable which optionally takes procedures. The registered `func` needs to be a callable which optionally
`ProcCtx` as its first argument. Other arguments of `func` will be bound to takes `ProcCtx` as the first argument. Other arguments of `func` will be
values passed in the cypherQuery. The full signature of `func` needs to be bound to values passed in the cypherQuery. The full signature of `func`
annotated with types. The return type must be `Record(field_name=type, ...)` needs to be annotated with types. The return type must be
and the procedure must produce either a complete Record or None. To mark a `Record(field_name=type, ...)` and the procedure must produce either a
field as deprecated, use `Record(field_name=Deprecated(type), ...)`. complete Record or None. To mark a field as deprecated, use
Multiple records can be produced by returning an iterable of them. `Record(field_name=Deprecated(type), ...)`. Multiple records can be
Registering generator functions is currently not supported. produced by returning an iterable of them. Registering generator functions
is currently not supported.
Example usage. Example usage.
@@ -1221,16 +1207,16 @@ def write_proc(func: typing.Callable[..., Record]):
""" """
Register `func` as a writeable procedure of the current module. Register `func` as a writeable procedure of the current module.
The decorator `write_proc` is meant to be used to register module `write_proc` is meant to be used as a decorator function to register module
procedures. The registered `func` needs to be a callable which optionally procedures. The registered `func` needs to be a callable which optionally
takes `ProcCtx` as the first argument. Other arguments of `func` will be takes `ProcCtx` as the first argument. Other arguments of `func` will be
bound to values passed in the cypherQuery. The full signature of `func` bound to values passed in the cypherQuery. The full signature of `func`
needs to be annotated with types. The return type must be needs to be annotated with types. The return type must be
`Record(field_name=type, ...)` and the procedure must produce either a `Record(field_name=type, ...)` and the procedure must produce either a
complete Record or None. To mark a field as deprecated, use complete Record or None. To mark a field as deprecated, use
`Record(field_name=Deprecated(type), ...)`. Multiple records can be produced `Record(field_name=Deprecated(type), ...)`. Multiple records can be
by returning an iterable of them. Registering generator functions is produced by returning an iterable of them. Registering generator functions
currently not supported. is currently not supported.
Example usage. Example usage.
@@ -1271,22 +1257,20 @@ class InvalidMessageError(Exception):
""" """
Signals using a message instance outside of the registered transformation. Signals using a message instance outside of the registered transformation.
""" """
pass pass
SOURCE_TYPE_KAFKA = _mgp.SOURCE_TYPE_KAFKA SOURCE_TYPE_KAFKA = _mgp.SOURCE_TYPE_KAFKA
SOURCE_TYPE_PULSAR = _mgp.SOURCE_TYPE_PULSAR SOURCE_TYPE_PULSAR = _mgp.SOURCE_TYPE_PULSAR
class Message: class Message:
"""Represents a message from a stream.""" """Represents a message from a stream."""
__slots__ = ('_message',)
__slots__ = ("_message",)
def __init__(self, message): def __init__(self, message):
if not isinstance(message, _mgp.Message): if not isinstance(message, _mgp.Message):
raise TypeError("Expected '_mgp.Message', got '{}'".format(type(message))) raise TypeError(
"Expected '_mgp.Message', got '{}'".format(type(message)))
self._message = message self._message = message
def __deepcopy__(self, memo): def __deepcopy__(self, memo):
@@ -1369,18 +1353,17 @@ class Message:
class InvalidMessagesError(Exception): class InvalidMessagesError(Exception):
"""Signals using a messages instance outside of the registered transformation.""" """Signals using a messages instance outside of the registered transformation."""
pass pass
class Messages: class Messages:
"""Represents a list of messages from a stream.""" """Represents a list of messages from a stream."""
__slots__ = ('_messages',)
__slots__ = ("_messages",)
def __init__(self, messages): def __init__(self, messages):
if not isinstance(messages, _mgp.Messages): if not isinstance(messages, _mgp.Messages):
raise TypeError("Expected '_mgp.Messages', got '{}'".format(type(messages))) raise TypeError(
"Expected '_mgp.Messages', got '{}'".format(type(messages)))
self._messages = messages self._messages = messages
def __deepcopy__(self, memo): def __deepcopy__(self, memo):
@@ -1412,12 +1395,12 @@ class TransCtx:
Access to a TransCtx is only valid during a single execution of a transformation. Access to a TransCtx is only valid during a single execution of a transformation.
You should not globally store a TransCtx instance. You should not globally store a TransCtx instance.
""" """
__slots__ = ('_graph')
__slots__ = "_graph"
def __init__(self, graph): def __init__(self, graph):
if not isinstance(graph, _mgp.Graph): if not isinstance(graph, _mgp.Graph):
raise TypeError("Expected '_mgp.Graph', got '{}'".format(type(graph))) raise TypeError(
"Expected '_mgp.Graph', got '{}'".format(type(graph)))
self._graph = Graph(graph) self._graph = Graph(graph)
def is_valid(self) -> bool: def is_valid(self) -> bool:
@@ -1437,116 +1420,21 @@ def transformation(func: typing.Callable[..., Record]):
params = tuple(sig.parameters.values()) params = tuple(sig.parameters.values())
if not params or not params[0].annotation is Messages: if not params or not params[0].annotation is Messages:
if not len(params) == 2 or not params[1].annotation is Messages: if not len(params) == 2 or not params[1].annotation is Messages:
raise NotImplementedError("Valid signatures for transformations are (TransCtx, Messages) or (Messages)") raise NotImplementedError(
"Valid signatures for transformations are (TransCtx, Messages) or (Messages)")
if params[0].annotation is TransCtx: if params[0].annotation is TransCtx:
@wraps(func) @wraps(func)
def wrapper(graph, messages): def wrapper(graph, messages):
return func(TransCtx(graph), messages) return func(TransCtx(graph), messages)
_mgp._MODULE.add_transformation(wrapper) _mgp._MODULE.add_transformation(wrapper)
else: else:
@wraps(func) @wraps(func)
def wrapper(graph, messages): def wrapper(graph, messages):
return func(messages) return func(messages)
_mgp._MODULE.add_transformation(wrapper) _mgp._MODULE.add_transformation(wrapper)
return func return func
class FuncCtx:
"""Context of a function being executed.
Access to a FuncCtx is only valid during a single execution of a function in
a query. You should not globally store a FuncCtx instance. The graph object
within the FuncCtx is not mutable.
"""
__slots__ = "_graph"
def __init__(self, graph):
if not isinstance(graph, _mgp.Graph):
raise TypeError("Expected '_mgp.Graph', got '{}'".format(type(graph)))
self._graph = Graph(graph)
def is_valid(self) -> bool:
return self._graph.is_valid()
def function(func: typing.Callable):
"""
Register `func` as a user-defined function in the current module.
The decorator `function` is meant to be used to register module functions.
The registered `func` needs to be a callable which optionally takes
`FuncCtx` as its first argument. Other arguments of `func` will be bound to
values passed in the Cypher query. Only the funcion arguments need to be
annotated with types. The return type doesn't need to be specified, but it
has to be supported by `mgp.Any`. Registering generator functions is
currently not supported.
Example usage.
```
import mgp
@mgp.function
def func_example(context: mgp.FuncCtx,
required_arg: str,
optional_arg: mgp.Nullable[str] = None
):
return_args = [required_arg]
if optional_arg is not None:
return_args.append(optional_arg)
# Return any kind of result supported by mgp.Any
return return_args
```
The example function above returns a list of provided arguments:
* `required_arg` is always present and its value is the first argument of
the function.
* `optional_arg` is present if the second argument of the function is not
`null`.
Any errors can be reported by raising an Exception.
The function can be invoked in Cypher using the following calls:
RETURN example.func_example("first argument", "second_argument");
RETURN example.func_example("first argument");
Naturally, you may pass in different arguments.
"""
raise_if_does_not_meet_requirements(func)
register_func = _mgp.Module.add_function
sig = inspect.signature(func)
params = tuple(sig.parameters.values())
if params and params[0].annotation is FuncCtx:
@wraps(func)
def wrapper(graph, args):
return func(FuncCtx(graph), *args)
params = params[1:]
mgp_func = register_func(_mgp._MODULE, wrapper)
else:
@wraps(func)
def wrapper(graph, args):
return func(*args)
mgp_func = register_func(_mgp._MODULE, wrapper)
for param in params:
name = param.name
type_ = param.annotation
if type_ is param.empty:
type_ = object
cypher_type = _typing_to_cypher_type(type_)
if param.default is param.empty:
mgp_func.add_arg(name, cypher_type)
else:
mgp_func.add_opt_arg(name, cypher_type, param.default)
return func
def _wrap_exceptions(): def _wrap_exceptions():
def wrap_function(func): def wrap_function(func):
@wraps(func) @wraps(func)
@@ -1575,7 +1463,6 @@ def _wrap_exceptions():
raise ValueConversionError(e) raise ValueConversionError(e)
except _mgp.SerializationError as e: except _mgp.SerializationError as e:
raise SerializationError(e) raise SerializationError(e)
return wrapped_func return wrapped_func
def wrap_prop_func(func): def wrap_prop_func(func):
@@ -1586,16 +1473,11 @@ def _wrap_exceptions():
if inspect.isfunction(obj): if inspect.isfunction(obj):
setattr(cls, name, wrap_function(obj)) setattr(cls, name, wrap_function(obj))
elif isinstance(obj, property): elif isinstance(obj, property):
setattr( setattr(cls, name, property(
cls, wrap_prop_func(obj.fget),
name, wrap_prop_func(obj.fset),
property( wrap_prop_func(obj.fdel),
wrap_prop_func(obj.fget), obj.__doc__))
wrap_prop_func(obj.fset),
wrap_prop_func(obj.fdel),
obj.__doc__,
),
)
def defined_in_this_module(obj: object): def defined_in_this_module(obj: object):
return getattr(obj, "__module__", "") == __name__ return getattr(obj, "__module__", "") == __name__

16
init
View File

@@ -24,7 +24,7 @@ function setup_virtualenv () {
fi fi
# create new virtualenv # create new virtualenv
python3 -m virtualenv -p python3 ve3 || exit 1 virtualenv -p python3 ve3 || exit 1
source ve3/bin/activate source ve3/bin/activate
pip --timeout 1000 install -r requirements.txt || exit 1 pip --timeout 1000 install -r requirements.txt || exit 1
deactivate deactivate
@@ -65,14 +65,8 @@ else
fi fi
DISTRO=$(operating_system) DISTRO=$(operating_system)
ARCHITECTURE=$(architecture) echo "ALL BUILD PACKAGES: $($DIR/environment/os/$DISTRO.sh list MEMGRAPH_BUILD_DEPS)"
if [ "${ARCHITECTURE}" = "arm64" ] || [ "${ARCHITECTURE}" = "aarch64" ]; then $DIR/environment/os/$DISTRO.sh check MEMGRAPH_BUILD_DEPS
OS_SCRIPT=$DIR/environment/os/$DISTRO-arm.sh
else
OS_SCRIPT=$DIR/environment/os/$DISTRO.sh
fi
echo "ALL BUILD PACKAGES: $($OS_SCRIPT list MEMGRAPH_BUILD_DEPS)"
$OS_SCRIPT check MEMGRAPH_BUILD_DEPS
echo "All packages are in-place..." echo "All packages are in-place..."
# create a default build directory # create a default build directory
@@ -135,7 +129,3 @@ for hook in $(find $DIR/.githooks -type f -printf "%f\n"); do
ln -s -f "$DIR/.githooks/$hook" "$DIR/.git/hooks/$hook" ln -s -f "$DIR/.githooks/$hook" "$DIR/.git/hooks/$hook"
echo "Added $hook hook" echo "Added $hook hook"
done; done;
# Install precommit hook
python3 -m pip install pre-commit
python3 -m pre_commit install

1
libs/.gitignore vendored
View File

@@ -4,4 +4,5 @@
!cleanup.sh !cleanup.sh
!CMakeLists.txt !CMakeLists.txt
!__main.cpp !__main.cpp
!jemalloc.cmake
!pulsar.patch !pulsar.patch

55
libs/jemalloc.cmake Normal file
View File

@@ -0,0 +1,55 @@
set(JEMALLOC_DIR "${LIB_DIR}/jemalloc")
set(JEMALLOC_SRCS
${JEMALLOC_DIR}/src/arena.c
${JEMALLOC_DIR}/src/background_thread.c
${JEMALLOC_DIR}/src/base.c
${JEMALLOC_DIR}/src/bin.c
${JEMALLOC_DIR}/src/bitmap.c
${JEMALLOC_DIR}/src/ckh.c
${JEMALLOC_DIR}/src/ctl.c
${JEMALLOC_DIR}/src/div.c
${JEMALLOC_DIR}/src/extent.c
${JEMALLOC_DIR}/src/extent_dss.c
${JEMALLOC_DIR}/src/extent_mmap.c
${JEMALLOC_DIR}/src/hash.c
${JEMALLOC_DIR}/src/hook.c
${JEMALLOC_DIR}/src/jemalloc.c
${JEMALLOC_DIR}/src/large.c
${JEMALLOC_DIR}/src/log.c
${JEMALLOC_DIR}/src/malloc_io.c
${JEMALLOC_DIR}/src/mutex.c
${JEMALLOC_DIR}/src/mutex_pool.c
${JEMALLOC_DIR}/src/nstime.c
${JEMALLOC_DIR}/src/pages.c
${JEMALLOC_DIR}/src/prng.c
${JEMALLOC_DIR}/src/prof.c
${JEMALLOC_DIR}/src/rtree.c
${JEMALLOC_DIR}/src/sc.c
${JEMALLOC_DIR}/src/stats.c
${JEMALLOC_DIR}/src/sz.c
${JEMALLOC_DIR}/src/tcache.c
${JEMALLOC_DIR}/src/test_hooks.c
${JEMALLOC_DIR}/src/ticker.c
${JEMALLOC_DIR}/src/tsd.c
${JEMALLOC_DIR}/src/witness.c
${JEMALLOC_DIR}/src/safety_check.c
)
add_library(jemalloc ${JEMALLOC_SRCS})
target_include_directories(jemalloc PUBLIC "${JEMALLOC_DIR}/include")
find_package(Threads REQUIRED)
target_link_libraries(jemalloc PUBLIC Threads::Threads)
target_compile_definitions(jemalloc PRIVATE -DJEMALLOC_NO_PRIVATE_NAMESPACE)
if (CMAKE_BUILD_TYPE STREQUAL "DEBUG")
target_compile_definitions(jemalloc PRIVATE -DJEMALLOC_DEBUG=1 -DJEMALLOC_PROF=1)
endif()
target_compile_options(jemalloc PRIVATE -Wno-redundant-decls)
# for RTLD_NEXT
target_compile_definitions(jemalloc PRIVATE _GNU_SOURCE)
set_property(TARGET jemalloc APPEND PROPERTY INTERFACE_COMPILE_DEFINITIONS USE_JEMALLOC=1)

View File

@@ -107,19 +107,25 @@ declare -A primary_urls=(
["antlr4-code"]="http://$local_cache_host/git/antlr4.git" ["antlr4-code"]="http://$local_cache_host/git/antlr4.git"
["antlr4-generator"]="http://$local_cache_host/file/antlr-4.9.2-complete.jar" ["antlr4-generator"]="http://$local_cache_host/file/antlr-4.9.2-complete.jar"
["cppitertools"]="http://$local_cache_host/git/cppitertools.git" ["cppitertools"]="http://$local_cache_host/git/cppitertools.git"
["fmt"]="http://$local_cache_host/git/fmt.git"
["rapidcheck"]="http://$local_cache_host/git/rapidcheck.git" ["rapidcheck"]="http://$local_cache_host/git/rapidcheck.git"
["gbenchmark"]="http://$local_cache_host/git/benchmark.git" ["gbenchmark"]="http://$local_cache_host/git/benchmark.git"
["gtest"]="http://$local_cache_host/git/googletest.git" ["gtest"]="http://$local_cache_host/git/googletest.git"
["gflags"]="http://$local_cache_host/git/gflags.git"
["libbcrypt"]="http://$local_cache_host/git/libbcrypt.git" ["libbcrypt"]="http://$local_cache_host/git/libbcrypt.git"
["bzip2"]="http://$local_cache_host/git/bzip2.git"
["zlib"]="http://$local_cache_host/git/zlib.git"
["rocksdb"]="http://$local_cache_host/git/rocksdb.git" ["rocksdb"]="http://$local_cache_host/git/rocksdb.git"
["mgclient"]="http://$local_cache_host/git/mgclient.git" ["mgclient"]="http://$local_cache_host/git/mgclient.git"
["pymgclient"]="http://$local_cache_host/git/pymgclient.git" ["pymgclient"]="http://$local_cache_host/git/pymgclient.git"
["mgconsole"]="http://$local_cache_host/git/mgconsole.git" ["mgconsole"]="http://$local_cache_host/git/mgconsole.git"
["spdlog"]="http://$local_cache_host/git/spdlog" ["spdlog"]="http://$local_cache_host/git/spdlog"
["jemalloc"]="http://$local_cache_host/git/jemalloc.git"
["nlohmann"]="http://$local_cache_host/file/nlohmann/json/4f8fba14066156b73f1189a2b8bd568bde5284c5/single_include/nlohmann/json.hpp" ["nlohmann"]="http://$local_cache_host/file/nlohmann/json/4f8fba14066156b73f1189a2b8bd568bde5284c5/single_include/nlohmann/json.hpp"
["neo4j"]="http://$local_cache_host/file/neo4j-community-3.2.3-unix.tar.gz" ["neo4j"]="http://$local_cache_host/file/neo4j-community-3.2.3-unix.tar.gz"
["librdkafka"]="http://$local_cache_host/git/librdkafka.git" ["librdkafka"]="http://$local_cache_host/git/librdkafka.git"
["protobuf"]="http://$local_cache_host/git/protobuf.git" ["protobuf"]="http://$local_cache_host/git/protobuf.git"
["boost"]="http://$local_cache_host/file/boost_1_77_0.tar.gz"
["pulsar"]="http://$local_cache_host/git/pulsar.git" ["pulsar"]="http://$local_cache_host/git/pulsar.git"
["librdtsc"]="http://$local_cache_host/git/librdtsc.git" ["librdtsc"]="http://$local_cache_host/git/librdtsc.git"
) )
@@ -132,19 +138,25 @@ declare -A secondary_urls=(
["antlr4-code"]="https://github.com/antlr/antlr4.git" ["antlr4-code"]="https://github.com/antlr/antlr4.git"
["antlr4-generator"]="http://www.antlr.org/download/antlr-4.9.2-complete.jar" ["antlr4-generator"]="http://www.antlr.org/download/antlr-4.9.2-complete.jar"
["cppitertools"]="https://github.com/ryanhaining/cppitertools.git" ["cppitertools"]="https://github.com/ryanhaining/cppitertools.git"
["fmt"]="https://github.com/fmtlib/fmt.git"
["rapidcheck"]="https://github.com/emil-e/rapidcheck.git" ["rapidcheck"]="https://github.com/emil-e/rapidcheck.git"
["gbenchmark"]="https://github.com/google/benchmark.git" ["gbenchmark"]="https://github.com/google/benchmark.git"
["gtest"]="https://github.com/google/googletest.git" ["gtest"]="https://github.com/google/googletest.git"
["gflags"]="https://github.com/memgraph/gflags.git"
["libbcrypt"]="https://github.com/rg3/libbcrypt" ["libbcrypt"]="https://github.com/rg3/libbcrypt"
["bzip2"]="https://github.com/VFR-maniac/bzip2"
["zlib"]="https://github.com/madler/zlib.git"
["rocksdb"]="https://github.com/facebook/rocksdb.git" ["rocksdb"]="https://github.com/facebook/rocksdb.git"
["mgclient"]="https://github.com/memgraph/mgclient.git" ["mgclient"]="https://github.com/memgraph/mgclient.git"
["pymgclient"]="https://github.com/memgraph/pymgclient.git" ["pymgclient"]="https://github.com/memgraph/pymgclient.git"
["mgconsole"]="http://github.com/memgraph/mgconsole.git" ["mgconsole"]="http://github.com/memgraph/mgconsole.git"
["spdlog"]="https://github.com/gabime/spdlog" ["spdlog"]="https://github.com/gabime/spdlog"
["jemalloc"]="https://github.com/jemalloc/jemalloc.git"
["nlohmann"]="https://raw.githubusercontent.com/nlohmann/json/4f8fba14066156b73f1189a2b8bd568bde5284c5/single_include/nlohmann/json.hpp" ["nlohmann"]="https://raw.githubusercontent.com/nlohmann/json/4f8fba14066156b73f1189a2b8bd568bde5284c5/single_include/nlohmann/json.hpp"
["neo4j"]="https://s3-eu-west-1.amazonaws.com/deps.memgraph.io/neo4j-community-3.2.3-unix.tar.gz" ["neo4j"]="https://s3-eu-west-1.amazonaws.com/deps.memgraph.io/neo4j-community-3.2.3-unix.tar.gz"
["librdkafka"]="https://github.com/edenhill/librdkafka.git" ["librdkafka"]="https://github.com/edenhill/librdkafka.git"
["protobuf"]="https://github.com/protocolbuffers/protobuf.git" ["protobuf"]="https://github.com/protocolbuffers/protobuf.git"
["boost"]="https://boostorg.jfrog.io/artifactory/main/release/1.77.0/source/boost_1_77_0.tar.gz"
["pulsar"]="https://github.com/apache/pulsar.git" ["pulsar"]="https://github.com/apache/pulsar.git"
["librdtsc"]="https://github.com/gabrieleara/librdtsc.git" ["librdtsc"]="https://github.com/gabrieleara/librdtsc.git"
) )
@@ -199,8 +211,8 @@ git apply ../rocksdb.patch
popd popd
# mgclient # mgclient
mgclient_tag="96e95c6845463cbe88948392be58d26da0d5ffd3" # (2022-02-08) mgclient_tag="v1.3.0" # (2021-09-23)
repo_clone_try_double "${primary_urls[mgclient]}" "${secondary_urls[mgclient]}" "mgclient" "$mgclient_tag" repo_clone_try_double "${primary_urls[mgclient]}" "${secondary_urls[mgclient]}" "mgclient" "$mgclient_tag" true
sed -i 's/\${CMAKE_INSTALL_LIBDIR}/lib/' mgclient/src/CMakeLists.txt sed -i 's/\${CMAKE_INSTALL_LIBDIR}/lib/' mgclient/src/CMakeLists.txt
# pymgclient # pymgclient

View File

@@ -36,7 +36,7 @@ ADDITIONAL USE GRANT: You may use the Licensed Work in accordance with the
3. using the Licensed Work to create a work or solution 3. using the Licensed Work to create a work or solution
which competes (or might reasonably be expected to which competes (or might reasonably be expected to
compete) with the Licensed Work. compete) with the Licensed Work.
CHANGE DATE: 2026-27-04 CHANGE DATE: 2025-12-08
CHANGE LICENSE: Apache License, Version 2.0 CHANGE LICENSE: Apache License, Version 2.0
For information about alternative licensing arrangements, please visit: https://memgraph.com/legal. For information about alternative licensing arrangements, please visit: https://memgraph.com/legal.

View File

@@ -7,11 +7,13 @@ import copy
@mgp.read_proc @mgp.read_proc
def procedure( def procedure(context: mgp.ProcCtx,
context: mgp.ProcCtx, required_arg: mgp.Nullable[mgp.Any],
required_arg: mgp.Nullable[mgp.Any], optional_arg: mgp.Nullable[mgp.Any] = None
optional_arg: mgp.Nullable[mgp.Any] = None, ) -> mgp.Record(args=list,
) -> mgp.Record(args=list, vertex_count=int, avg_degree=mgp.Number, props=mgp.Nullable[mgp.Map]): vertex_count=int,
avg_degree=mgp.Number,
props=mgp.Nullable[mgp.Map]):
""" """
This example procedure returns 4 fields. This example procedure returns 4 fields.
@@ -35,7 +37,7 @@ def procedure(
if isinstance(required_arg, (mgp.Edge, mgp.Vertex)): if isinstance(required_arg, (mgp.Edge, mgp.Vertex)):
props = dict(required_arg.properties.items()) props = dict(required_arg.properties.items())
elif isinstance(required_arg, mgp.Path): elif isinstance(required_arg, mgp.Path):
(start_vertex,) = required_arg.vertices start_vertex, = required_arg.vertices
props = dict(start_vertex.properties.items()) props = dict(start_vertex.properties.items())
# Count the vertices and edges in the database; this may take a while. # Count the vertices and edges in the database; this may take a while.
vertex_count = 0 vertex_count = 0
@@ -49,13 +51,15 @@ def procedure(
# Copy the received arguments to make it equivalent to the C example. # Copy the received arguments to make it equivalent to the C example.
args_copy = [copy.deepcopy(required_arg), copy.deepcopy(optional_arg)] args_copy = [copy.deepcopy(required_arg), copy.deepcopy(optional_arg)]
# Multiple rows can be produced by returning an iterable of mgp.Record. # Multiple rows can be produced by returning an iterable of mgp.Record.
return mgp.Record(args=args_copy, vertex_count=vertex_count, avg_degree=avg_degree, props=props) return mgp.Record(args=args_copy, vertex_count=vertex_count,
avg_degree=avg_degree, props=props)
@mgp.write_proc @mgp.write_proc
def write_procedure( def write_procedure(context: mgp.ProcCtx,
context: mgp.ProcCtx, property_name: str, property_value: mgp.Nullable[mgp.Any] property_name: str,
) -> mgp.Record(created_vertex=mgp.Vertex): property_value: mgp.Nullable[mgp.Any]
) -> mgp.Record(created_vertex=mgp.Vertex):
""" """
This example procedure creates a new vertex with the specified property This example procedure creates a new vertex with the specified property
and connects it to all existing vertex which has the same property with and connects it to all existing vertex which has the same property with

View File

@@ -4,17 +4,15 @@ from collections import OrderedDict
from itertools import chain, repeat from itertools import chain, repeat
from inspect import cleandoc from inspect import cleandoc
from typing import List, Tuple from typing import List, Tuple
try: try:
import networkx as nx import networkx as nx
except ImportError as import_error: except ImportError as import_error:
sys.stderr.write( sys.stderr.write((
( '\n'
"\n" 'NOTE: Please install networkx to be able to use graph_analyzer '
"NOTE: Please install networkx to be able to use graph_analyzer " 'module. Using Python:\n'
"module. Using Python:\n" + sys.version + "\n" + sys.version +
) '\n'))
)
raise import_error raise import_error
# Imported last because it also depends on networkx. # Imported last because it also depends on networkx.
from mgp_networkx import MemgraphMultiDiGraph # noqa E402 from mgp_networkx import MemgraphMultiDiGraph # noqa E402
@@ -25,14 +23,16 @@ _MAX_LIST_SIZE = 10
@mgp.read_proc @mgp.read_proc
def help() -> mgp.Record(name=str, value=str): def help() -> mgp.Record(name=str, value=str):
"""Shows manual page for graph_analyzer.""" '''Shows manual page for graph_analyzer.'''
records = [] records = []
def make_records(name, doc): def make_records(name, doc):
return (mgp.Record(name=n, value=v) for n, v in zip(chain([name], repeat("")), cleandoc(doc).splitlines())) return (mgp.Record(name=n, value=v) for n, v in
zip(chain([name], repeat('')), cleandoc(doc).splitlines()))
for func in (help, analyze, analyze_subgraph): for func in (help, analyze, analyze_subgraph):
records.extend(make_records("Procedure '{}'".format(func.__name__), func.__doc__)) records.extend(make_records("Procedure '{}'".format(func.__name__),
func.__doc__))
for m, v in _get_analysis_mapping().items(): for m, v in _get_analysis_mapping().items():
records.extend(make_records("Analysis '{}'".format(m), v.__doc__)) records.extend(make_records("Analysis '{}'".format(m), v.__doc__))
@@ -41,8 +41,10 @@ def help() -> mgp.Record(name=str, value=str):
@mgp.read_proc @mgp.read_proc
def analyze(context: mgp.ProcCtx, analyses: mgp.Nullable[List[str]] = None) -> mgp.Record(name=str, value=str): def analyze(context: mgp.ProcCtx,
""" analyses: mgp.Nullable[List[str]] = None
) -> mgp.Record(name=str, value=str):
'''
Shows graph information. Shows graph information.
In case of multiple results, only the first 10 will be shown. In case of multiple results, only the first 10 will be shown.
@@ -55,20 +57,19 @@ def analyze(context: mgp.ProcCtx, analyses: mgp.Nullable[List[str]] = None) -> m
Example call (with parameter): Example call (with parameter):
CALL graph_analyzer.analyze(['nodes', 'edges']) YIELD *; CALL graph_analyzer.analyze(['nodes', 'edges']) YIELD *;
""" '''
g = MemgraphMultiDiGraph(ctx=context) g = MemgraphMultiDiGraph(ctx=context)
recs = _analyze_graph(context, g, analyses) recs = _analyze_graph(context, g, analyses)
return [mgp.Record(name=name, value=value) for name, value in recs] return [mgp.Record(name=name, value=value) for name, value in recs]
@mgp.read_proc @mgp.read_proc
def analyze_subgraph( def analyze_subgraph(context: mgp.ProcCtx,
context: mgp.ProcCtx, vertices: mgp.List[mgp.Vertex],
vertices: mgp.List[mgp.Vertex], edges: mgp.List[mgp.Edge],
edges: mgp.List[mgp.Edge], analyses: mgp.Nullable[List[str]] = None
analyses: mgp.Nullable[List[str]] = None, ) -> mgp.Record(name=str, value=str):
) -> mgp.Record(name=str, value=str): '''
"""
Shows subgraph information. Shows subgraph information.
In case of multiple results, only the first 10 will be shown. In case of multiple results, only the first 10 will be shown.
@@ -90,40 +91,36 @@ def analyze_subgraph(
CALL graph_analyzer.analyze_subgraph(nodes, edges, ['nodes', 'edges']) CALL graph_analyzer.analyze_subgraph(nodes, edges, ['nodes', 'edges'])
YIELD * YIELD *
RETURN name, value; RETURN name, value;
""" '''
vertices, edges = map(set, [vertices, edges]) vertices, edges = map(set, [vertices, edges])
g = nx.subgraph_view( g = nx.subgraph_view(
MemgraphMultiDiGraph(ctx=context), MemgraphMultiDiGraph(ctx=context),
lambda n: n in vertices, lambda n: n in vertices,
lambda n1, n2, e: e in edges, lambda n1, n2, e: e in edges)
)
recs = _analyze_graph(context, g, analyses) recs = _analyze_graph(context, g, analyses)
return [mgp.Record(name=name, value=value) for name, value in recs] return [mgp.Record(name=name, value=value) for name, value in recs]
def _get_analysis_mapping(): def _get_analysis_mapping():
return OrderedDict( return OrderedDict([
[ ('nodes', _number_of_nodes),
("nodes", _number_of_nodes), ('edges', _number_of_edges),
("edges", _number_of_edges), ('bridges', _bridges),
("bridges", _bridges), ('articulation_points', _articulation_points),
("articulation_points", _articulation_points), ('avg_degree', _avg_degree),
("avg_degree", _avg_degree), ('sorted_nodes_degree', _sorted_nodes_degree),
("sorted_nodes_degree", _sorted_nodes_degree), ('self_loops', _self_loops),
("self_loops", _self_loops), ('is_bipartite', _is_bipartite),
("is_bipartite", _is_bipartite), ('is_planar', _is_planar),
("is_planar", _is_planar), ('is_biconnected: ', _is_biconnected),
("is_biconnected: ", _is_biconnected), ('is_weakly_connected', _is_weakly_connected),
("is_weakly_connected", _is_weakly_connected), ('number_of_weakly_components', _weakly_components),
("number_of_weakly_components", _weakly_components), ('is_strongly_connected', _is_strongly_connected),
("is_strongly_connected", _is_strongly_connected), ('strongly_components', _strongly_components),
("strongly_components", _strongly_components), ('is_dag', _is_dag),
("is_dag", _is_dag), ('is_eulerian', _is_eulerian),
("is_eulerian", _is_eulerian), ('is_forest', _is_forest),
("is_forest", _is_forest), ('is_tree', _is_tree)])
("is_tree", _is_tree),
]
)
def _get_analysis_func(name: str): def _get_analysis_func(name: str):
@@ -135,15 +132,20 @@ def _get_analysis_funcs():
return _get_analysis_mapping().values() return _get_analysis_mapping().values()
def _analyze_graph(context: mgp.ProcCtx, g: nx.MultiDiGraph, analyses: List[str]) -> List[Tuple[str, str]]: def _analyze_graph(context: mgp.ProcCtx,
g: nx.MultiDiGraph,
analyses: List[str]
) -> List[Tuple[str, str]]:
functions = _get_analysis_funcs() if analyses is None else [_get_analysis_func(name) for name in analyses] functions = (_get_analysis_funcs() if analyses is None
else [_get_analysis_func(name) for name in analyses])
records = [] records = []
for index, f in enumerate(functions): for index, f in enumerate(functions):
context.check_must_abort() context.check_must_abort()
if f is None: if f is None:
raise KeyError("Graph analysis is not supported: " + analyses[index]) raise KeyError('Graph analysis is not supported: ' +
analyses[index])
name, value = f(g) name, value = f(g)
if isinstance(value, (list, set, tuple)): if isinstance(value, (list, set, tuple)):
value = list(value)[:_MAX_LIST_SIZE] value = list(value)[:_MAX_LIST_SIZE]
@@ -153,120 +155,126 @@ def _analyze_graph(context: mgp.ProcCtx, g: nx.MultiDiGraph, analyses: List[str]
def _number_of_nodes(g: nx.MultiDiGraph) -> Tuple[str, int]: def _number_of_nodes(g: nx.MultiDiGraph) -> Tuple[str, int]:
"""Returns number of nodes.""" '''Returns number of nodes.'''
return "Number of nodes", nx.number_of_nodes(g) return 'Number of nodes', nx.number_of_nodes(g)
def _number_of_edges(g: nx.MultiDiGraph) -> Tuple[str, int]: def _number_of_edges(g: nx.MultiDiGraph) -> Tuple[str, int]:
"""Returns number of edges.""" '''Returns number of edges.'''
return "Number of edges", nx.number_of_edges(g) return 'Number of edges', nx.number_of_edges(g)
def _avg_degree(g: nx.MultiDiGraph) -> Tuple[str, float]: def _avg_degree(g: nx.MultiDiGraph) -> Tuple[str, float]:
"""Returns average degree.""" '''Returns average degree.'''
_, number_of_nodes = _number_of_nodes(g) _, number_of_nodes = _number_of_nodes(g)
_, number_of_edges = _number_of_edges(g) _, number_of_edges = _number_of_edges(g)
avg_degree = 0 if number_of_nodes == 0 else number_of_edges / number_of_nodes avg_degree = (0 if number_of_nodes == 0
return "Average degree", avg_degree else number_of_edges / number_of_nodes)
return 'Average degree', avg_degree
def _sorted_nodes_degree(g: nx.MultiDiGraph) -> Tuple[str, List[int]]: def _sorted_nodes_degree(g: nx.MultiDiGraph) -> Tuple[str, List[int]]:
"""Returns list of sorted nodes degree. [(node_id, degree), ...]""" '''Returns list of sorted nodes degree. [(node_id, degree), ...]'''
nodes_degree = [(n, g.degree(n)) for n in g.nodes()] nodes_degree = [(n, g.degree(n)) for n in g.nodes()]
nodes_degree.sort(key=lambda x: x[1], reverse=True) nodes_degree.sort(key=lambda x: x[1], reverse=True)
return "Sorted nodes degree", nodes_degree return 'Sorted nodes degree', nodes_degree
def _self_loops(g: nx.MultiDiGraph) -> Tuple[str, int]: def _self_loops(g: nx.MultiDiGraph) -> Tuple[str, int]:
"""Returns number of self loops.""" '''Returns number of self loops.'''
return "Self loops", sum((1 if e[0] == e[1] else 0 for e in g.edges())) return 'Self loops', sum((1 if e[0] == e[1] else 0 for e in g.edges()))
def _is_bipartite(g: nx.MultiDiGraph) -> Tuple[str, bool]: def _is_bipartite(g: nx.MultiDiGraph) -> Tuple[str, bool]:
"""Checks if graph is bipartite.""" '''Checks if graph is bipartite.'''
_, number_of_nodes = _number_of_nodes(g) _, number_of_nodes = _number_of_nodes(g)
ret = False if number_of_nodes == 0 else nx.algorithms.bipartite.basic.is_bipartite(g) ret = (False if number_of_nodes == 0
return "Is bipartite", ret else nx.algorithms.bipartite.basic.is_bipartite(g))
return 'Is bipartite', ret
def _is_planar(g: nx.MultiDiGraph) -> Tuple[str, bool]: def _is_planar(g: nx.MultiDiGraph) -> Tuple[str, bool]:
"""Checks if graph is planar.""" '''Checks if graph is planar.'''
_, number_of_nodes = _number_of_nodes(g) _, number_of_nodes = _number_of_nodes(g)
ret = False if number_of_nodes == 0 else nx.algorithms.planarity.check_planarity(g)[0] ret = (False if number_of_nodes == 0
return "Is planar", ret else nx.algorithms.planarity.check_planarity(g)[0])
return 'Is planar', ret
def _is_biconnected(g: nx.MultiDiGraph) -> Tuple[str, bool]: def _is_biconnected(g: nx.MultiDiGraph) -> Tuple[str, bool]:
"""Check if graph is biconnected.""" '''Check if graph is biconnected.'''
_, number_of_nodes = _number_of_nodes(g) _, number_of_nodes = _number_of_nodes(g)
ret = False if number_of_nodes == 0 else nx.is_biconnected(nx.MultiDiGraph.to_undirected(g)) ret = (False if number_of_nodes == 0
return "Is biconnected", ret else nx.is_biconnected(nx.MultiDiGraph.to_undirected(g)))
return 'Is biconnected', ret
def _is_weakly_connected(g: nx.MultiDiGraph) -> Tuple[str, bool]: def _is_weakly_connected(g: nx.MultiDiGraph) -> Tuple[str, bool]:
"""Check if graph is weakly connected.""" '''Check if graph is weakly connected.'''
_, number_of_nodes = _number_of_nodes(g) _, number_of_nodes = _number_of_nodes(g)
ret = False if number_of_nodes == 0 else nx.is_weakly_connected(g) ret = False if number_of_nodes == 0 else nx.is_weakly_connected(g)
return "Is weakly connected", ret return 'Is weakly connected', ret
def _is_strongly_connected(g: nx.MultiDiGraph) -> Tuple[str, bool]: def _is_strongly_connected(g: nx.MultiDiGraph) -> Tuple[str, bool]:
"""Checks if graph is strongly connected.""" '''Checks if graph is strongly connected.'''
_, number_of_nodes = _number_of_nodes(g) _, number_of_nodes = _number_of_nodes(g)
ret = False if number_of_nodes == 0 else nx.is_strongly_connected(g) ret = False if number_of_nodes == 0 else nx.is_strongly_connected(g)
return "Is strongly connected", ret return 'Is strongly connected', ret
def _is_dag(g: nx.MultiDiGraph) -> Tuple[str, bool]: def _is_dag(g: nx.MultiDiGraph) -> Tuple[str, bool]:
"""Check if graph is directed acyclic graph (DAG)""" '''Check if graph is directed acyclic graph (DAG)'''
_, number_of_nodes = _number_of_nodes(g) _, number_of_nodes = _number_of_nodes(g)
ret = False if number_of_nodes == 0 else nx.algorithms.dag.is_directed_acyclic_graph(g) ret = (False if number_of_nodes == 0
return "Is DAG", ret else nx.algorithms.dag.is_directed_acyclic_graph(g))
return 'Is DAG', ret
def _is_eulerian(g: nx.MultiDiGraph) -> Tuple[str, bool]: def _is_eulerian(g: nx.MultiDiGraph) -> Tuple[str, bool]:
"""Checks if graph is Eulerian.""" '''Checks if graph is Eulerian.'''
_, number_of_nodes = _number_of_nodes(g) _, number_of_nodes = _number_of_nodes(g)
ret = False if number_of_nodes == 0 else nx.algorithms.euler.is_eulerian(g) ret = (False if number_of_nodes == 0
return "Is eulerian", ret else nx.algorithms.euler.is_eulerian(g))
return 'Is eulerian', ret
def _is_forest(g: nx.MultiDiGraph) -> Tuple[str, bool]: def _is_forest(g: nx.MultiDiGraph) -> Tuple[str, bool]:
"""Checks if graph is forest, all components must be trees.""" '''Checks if graph is forest, all components must be trees.'''
_, number_of_nodes = _number_of_nodes(g) _, number_of_nodes = _number_of_nodes(g)
ret = False if number_of_nodes == 0 else nx.algorithms.tree.recognition.is_forest(g) ret = (False if number_of_nodes == 0
return "Is forest", ret else nx.algorithms.tree.recognition.is_forest(g))
return 'Is forest', ret
def _is_tree(g: nx.MultiDiGraph) -> Tuple[str, bool]: def _is_tree(g: nx.MultiDiGraph) -> Tuple[str, bool]:
"""Checks if graph is tree.""" '''Checks if graph is tree.'''
_, number_of_nodes = _number_of_nodes(g) _, number_of_nodes = _number_of_nodes(g)
ret = False if number_of_nodes == 0 else nx.algorithms.tree.recognition.is_tree(g) ret = (False if number_of_nodes == 0
return "Is tree", ret else nx.algorithms.tree.recognition.is_tree(g))
return 'Is tree', ret
def _bridges(g: nx.MultiDiGraph) -> Tuple[str, int]: def _bridges(g: nx.MultiDiGraph) -> Tuple[str, int]:
"""Returns number of bridges, multiple edges between same nodes are '''Returns number of bridges, multiple edges between same nodes are
mapped to one edge.""" mapped to one edge.'''
return "Number of bridges", sum(1 for _ in nx.bridges(nx.Graph(g))) return 'Number of bridges', sum(1 for _ in nx.bridges(nx.Graph(g)))
def _articulation_points(g: nx.MultiDiGraph): def _articulation_points(g: nx.MultiDiGraph):
"""Returns number of articulation points.""" '''Returns number of articulation points.'''
undirected = nx.MultiDiGraph.to_undirected(g) undirected = nx.MultiDiGraph.to_undirected(g)
return ( return ('Number of articulation points',
"Number of articulation points", sum(1 for _ in nx.articulation_points(undirected)))
sum(1 for _ in nx.articulation_points(undirected)),
)
def _weakly_components(g: nx.MultiDiGraph): def _weakly_components(g: nx.MultiDiGraph):
"""Returns number of weakly components.""" '''Returns number of weakly components.'''
comps = nx.algorithms.components.number_weakly_connected_components(g) comps = nx.algorithms.components.number_weakly_connected_components(g)
return "Number of weakly connected components", comps return 'Number of weakly connected components', comps
def _strongly_components(g: nx.MultiDiGraph): def _strongly_components(g: nx.MultiDiGraph):
"""Returns number of strongly connected components.""" '''Returns number of strongly connected components.'''
comps = nx.algorithms.components.number_strongly_connected_components(g) comps = nx.algorithms.components.number_strongly_connected_components(g)
return "Number of strongly connected components", comps return 'Number of strongly connected components', comps

View File

@@ -1,22 +1,20 @@
import sys import sys
import mgp import mgp
import collections import collections
try: try:
import networkx as nx import networkx as nx
except ImportError as import_error: except ImportError as import_error:
sys.stderr.write( sys.stderr.write((
( '\n'
"\n" 'NOTE: Please install networkx to be able to use Memgraph NetworkX '
"NOTE: Please install networkx to be able to use Memgraph NetworkX " 'wrappers. Using Python:\n'
"wrappers. Using Python:\n" + sys.version + "\n" + sys.version +
) '\n'))
)
raise import_error raise import_error
class MemgraphAdjlistOuterDict(collections.abc.Mapping): class MemgraphAdjlistOuterDict(collections.abc.Mapping):
__slots__ = ("_ctx", "_succ", "_multi") __slots__ = ('_ctx', '_succ', '_multi')
def __init__(self, ctx, succ=True, multi=True): def __init__(self, ctx, succ=True, multi=True):
self._ctx = ctx self._ctx = ctx
@@ -26,7 +24,8 @@ class MemgraphAdjlistOuterDict(collections.abc.Mapping):
def __getitem__(self, key): def __getitem__(self, key):
if key not in self: if key not in self:
raise KeyError raise KeyError
return MemgraphAdjlistInnerDict(key, succ=self._succ, multi=self._multi) return MemgraphAdjlistInnerDict(key, succ=self._succ,
multi=self._multi)
def __iter__(self): def __iter__(self):
return iter(self._ctx.graph.vertices) return iter(self._ctx.graph.vertices)
@@ -41,7 +40,7 @@ class MemgraphAdjlistOuterDict(collections.abc.Mapping):
class MemgraphAdjlistInnerDict(collections.abc.Mapping): class MemgraphAdjlistInnerDict(collections.abc.Mapping):
__slots__ = ("_node", "_succ", "_multi", "_neighbors") __slots__ = ('_node', '_succ', '_multi', '_neighbors')
def __init__(self, node, succ=True, multi=True): def __init__(self, node, succ=True, multi=True):
self._node = node self._node = node
@@ -72,26 +71,31 @@ class MemgraphAdjlistInnerDict(collections.abc.Mapping):
def _get_neighbors(self): def _get_neighbors(self):
if not self._neighbors: if not self._neighbors:
if self._succ: if self._succ:
self._neighbors = set(e.to_vertex for e in self._node.out_edges) self._neighbors = set(
e.to_vertex for e in self._node.out_edges)
else: else:
self._neighbors = set(e.from_vertex for e in self._node.in_edges) self._neighbors = set(
e.from_vertex for e in self._node.in_edges)
return self._neighbors return self._neighbors
def _get_edge(self, neighbor): def _get_edge(self, neighbor):
if self._succ: if self._succ:
edge = list(filter(lambda e: e.to_vertex == neighbor, self._node.out_edges)) edge = list(filter(lambda e: e.to_vertex == neighbor,
self._node.out_edges))
else: else:
edge = list(filter(lambda e: e.from_vertex == neighbor, self._node.in_edges)) edge = list(filter(lambda e: e.from_vertex == neighbor,
self._node.in_edges))
assert len(edge) >= 1 assert len(edge) >= 1
if len(edge) > 1: if len(edge) > 1:
raise RuntimeError("Graph contains multiedges but " "is of non-multigraph type: {}".format(edge)) raise RuntimeError('Graph contains multiedges but '
'is of non-multigraph type: {}'.format(edge))
return edge[0] return edge[0]
class MemgraphEdgeKeyDict(collections.abc.Mapping): class MemgraphEdgeKeyDict(collections.abc.Mapping):
__slots__ = ("_node", "_neighbor", "_succ", "_edges") __slots__ = ('_node', '_neighbor', '_succ', '_edges')
def __init__(self, node, neighbor, succ=True): def __init__(self, node, neighbor, succ=True):
self._node = node self._node = node
@@ -118,14 +122,18 @@ class MemgraphEdgeKeyDict(collections.abc.Mapping):
def _get_edges(self): def _get_edges(self):
if not self._edges: if not self._edges:
if self._succ: if self._succ:
self._edges = list(filter(lambda e: e.to_vertex == self._neighbor, self._node.out_edges)) self._edges = list(filter(
lambda e: e.to_vertex == self._neighbor,
self._node.out_edges))
else: else:
self._edges = list(filter(lambda e: e.from_vertex == self._neighbor, self._node.in_edges)) self._edges = list(filter(
lambda e: e.from_vertex == self._neighbor,
self._node.in_edges))
return self._edges return self._edges
class UnhashableProperties(collections.abc.Mapping): class UnhashableProperties(collections.abc.Mapping):
__slots__ = "_properties" __slots__ = ('_properties')
def __init__(self, properties): def __init__(self, properties):
self._properties = properties self._properties = properties
@@ -147,7 +155,7 @@ class UnhashableProperties(collections.abc.Mapping):
class MemgraphNodeDict(collections.abc.Mapping): class MemgraphNodeDict(collections.abc.Mapping):
__slots__ = ("_ctx",) __slots__ = ('_ctx',)
def __init__(self, ctx): def __init__(self, ctx):
self._ctx = ctx self._ctx = ctx
@@ -179,7 +187,8 @@ class MemgraphNodeDict(collections.abc.Mapping):
class MemgraphDiGraphBase: class MemgraphDiGraphBase:
def __init__(self, incoming_graph_data=None, ctx=None, multi=True, **kwargs): def __init__(self, incoming_graph_data=None, ctx=None, multi=True,
**kwargs):
# NOTE: We assume that our graph will never be given any initial data # NOTE: We assume that our graph will never be given any initial data
# because we already pull our data from the Memgraph database. This # because we already pull our data from the Memgraph database. This
# assert is triggered by certain NetworkX procedures because they # assert is triggered by certain NetworkX procedures because they
@@ -192,30 +201,23 @@ class MemgraphDiGraphBase:
# modify the graph's internal attributes and don't try to populate it # modify the graph's internal attributes and don't try to populate it
# with initial data or modify it. # with initial data or modify it.
self.node_dict_factory = lambda: MemgraphNodeDict(ctx) if ctx else self._error self.node_dict_factory = lambda: MemgraphNodeDict(ctx) \
if ctx else self._error
self.node_attr_dict_factory = self._error self.node_attr_dict_factory = self._error
self.adjlist_outer_dict_factory = lambda: MemgraphAdjlistOuterDict(ctx, multi=multi) if ctx else self._error self.adjlist_outer_dict_factory = \
lambda: MemgraphAdjlistOuterDict(ctx, multi=multi) \
if ctx else self._error
self.adjlist_inner_dict_factory = self._error self.adjlist_inner_dict_factory = self._error
self.edge_key_dict_factory = self._error self.edge_key_dict_factory = self._error
self.edge_attr_dict_factory = self._error self.edge_attr_dict_factory = self._error
# NOTE: We forbid any mutating operations because our graph is # NOTE: We forbid any mutating operations because our graph is
# immutable and pulls its data from the Memgraph database. # immutable and pulls its data from the Memgraph database.
for f in [ for f in ['add_node', 'add_nodes_from', 'remove_node',
"add_node", 'remove_nodes_from', 'add_edge', 'add_edges_from',
"add_nodes_from", 'add_weighted_edges_from', 'new_edge_key', 'remove_edge',
"remove_node", 'remove_edges_from', 'update', 'clear']:
"remove_nodes_from",
"add_edge",
"add_edges_from",
"add_weighted_edges_from",
"new_edge_key",
"remove_edge",
"remove_edges_from",
"update",
"clear",
]:
setattr(self, f, lambda *args, **kwargs: self._error()) setattr(self, f, lambda *args, **kwargs: self._error())
super().__init__(None, **kwargs) super().__init__(None, **kwargs)
@@ -229,29 +231,33 @@ class MemgraphDiGraphBase:
self._pred = MemgraphAdjlistOuterDict(ctx, succ=False, multi=multi) self._pred = MemgraphAdjlistOuterDict(ctx, succ=False, multi=multi)
def _error(self): def _error(self):
raise RuntimeError("Modification operations are not supported") raise RuntimeError('Modification operations are not supported')
class MemgraphMultiDiGraph(MemgraphDiGraphBase, nx.MultiDiGraph): class MemgraphMultiDiGraph(MemgraphDiGraphBase, nx.MultiDiGraph):
def __init__(self, incoming_graph_data=None, ctx=None, **kwargs): def __init__(self, incoming_graph_data=None, ctx=None, **kwargs):
super().__init__(incoming_graph_data=incoming_graph_data, ctx=ctx, multi=True, **kwargs) super().__init__(incoming_graph_data=incoming_graph_data,
ctx=ctx, multi=True, **kwargs)
def MemgraphMultiGraph(incoming_graph_data=None, ctx=None, **kwargs): def MemgraphMultiGraph(incoming_graph_data=None, ctx=None, **kwargs):
return MemgraphMultiDiGraph(incoming_graph_data=incoming_graph_data, ctx=ctx, **kwargs).to_undirected(as_view=True) return MemgraphMultiDiGraph(incoming_graph_data=incoming_graph_data,
ctx=ctx, **kwargs).to_undirected(as_view=True)
class MemgraphDiGraph(MemgraphDiGraphBase, nx.DiGraph): class MemgraphDiGraph(MemgraphDiGraphBase, nx.DiGraph):
def __init__(self, incoming_graph_data=None, ctx=None, **kwargs): def __init__(self, incoming_graph_data=None, ctx=None, **kwargs):
super().__init__(incoming_graph_data=incoming_graph_data, ctx=ctx, multi=False, **kwargs) super().__init__(incoming_graph_data=incoming_graph_data,
ctx=ctx, multi=False, **kwargs)
def MemgraphGraph(incoming_graph_data=None, ctx=None, **kwargs): def MemgraphGraph(incoming_graph_data=None, ctx=None, **kwargs):
return MemgraphDiGraph(incoming_graph_data=incoming_graph_data, ctx=ctx, **kwargs).to_undirected(as_view=True) return MemgraphDiGraph(incoming_graph_data=incoming_graph_data,
ctx=ctx, **kwargs).to_undirected(as_view=True)
class PropertiesDictionary(collections.abc.Mapping): class PropertiesDictionary(collections.abc.Mapping):
__slots__ = ("_ctx", "_prop", "_len") __slots__ = ('_ctx', '_prop', '_len')
def __init__(self, ctx, prop): def __init__(self, ctx, prop):
self._ctx = ctx self._ctx = ctx
@@ -264,7 +270,8 @@ class PropertiesDictionary(collections.abc.Mapping):
try: try:
return vertex.properties[self._prop] return vertex.properties[self._prop]
except KeyError: except KeyError:
raise KeyError(("{} doesn\t have the required " + "property '{}'").format(vertex, self._prop)) raise KeyError(("{} doesn\t have the required " +
"property '{}'").format(vertex, self._prop))
def __iter__(self): def __iter__(self):
for v in self._ctx.graph.vertices: for v in self._ctx.graph.vertices:

File diff suppressed because it is too large Load Diff

View File

@@ -1,20 +1,23 @@
import sys import sys
import mgp import mgp
try: try:
import networkx as nx import networkx as nx
except ImportError as import_error: except ImportError as import_error:
sys.stderr.write( sys.stderr.write(
"\n" "NOTE: Please install networkx to be able to use wcc module.\n" "Using Python:\n" + sys.version + "\n" '\n'
) 'NOTE: Please install networkx to be able to use wcc module.\n'
'Using Python:\n'
+ sys.version +
'\n')
raise import_error raise import_error
@mgp.read_proc @mgp.read_proc
def get_components( def get_components(vertices: mgp.List[mgp.Vertex],
vertices: mgp.List[mgp.Vertex], edges: mgp.List[mgp.Edge] edges: mgp.List[mgp.Edge]
) -> mgp.Record(n_components=int, components=mgp.List[mgp.List[mgp.Vertex]]): ) -> mgp.Record(n_components=int,
""" components=mgp.List[mgp.List[mgp.Vertex]]):
'''
This procedure finds weakly connected components of a given subgraph of a This procedure finds weakly connected components of a given subgraph of a
directed graph. directed graph.
@@ -38,7 +41,7 @@ def get_components(
WITH collect(n) AS nodes, collect(e) AS edges WITH collect(n) AS nodes, collect(e) AS edges
CALL wcc.get_components(nodes, edges) YIELD * CALL wcc.get_components(nodes, edges) YIELD *
RETURN n_components, components; RETURN n_components, components;
""" '''
g = nx.DiGraph() g = nx.DiGraph()
g.add_nodes_from(vertices) g.add_nodes_from(vertices)
g.add_edges_from([(edge.from_vertex, edge.to_vertex) for edge in edges]) g.add_edges_from([(edge.from_vertex, edge.to_vertex) for edge in edges])

View File

@@ -10,14 +10,6 @@ set(CPACK_PACKAGE_VENDOR "Memgraph Ltd.")
set(CPACK_PACKAGE_DESCRIPTION_SUMMARY set(CPACK_PACKAGE_DESCRIPTION_SUMMARY
"High performance, in-memory, transactional graph database") "High performance, in-memory, transactional graph database")
# Setting arhitecture extension for deb packages
set(MG_ARCH_EXTENSION_DEB "all")
if (${MG_ARCH} STREQUAL "x86_64")
set(MG_ARCH_EXTENSION_DEB "amd64")
elseif (${MG_ARCH} STREQUAL "ARM64")
set(MG_ARCH_EXTENSION_DEB "arm64")
endif()
# DEB specific # DEB specific
# Instead of using "name <email>" format, we use "email (name)" to prevent # Instead of using "name <email>" format, we use "email (name)" to prevent
# errors due to full stop, '.' at the end of "Ltd". (See: RFC 822) # errors due to full stop, '.' at the end of "Ltd". (See: RFC 822)
@@ -25,7 +17,7 @@ set(CPACK_DEBIAN_PACKAGE_MAINTAINER "tech@memgraph.com (Memgraph Ltd.)")
set(CPACK_DEBIAN_PACKAGE_SECTION non-free/database) set(CPACK_DEBIAN_PACKAGE_SECTION non-free/database)
set(CPACK_DEBIAN_PACKAGE_HOMEPAGE https://memgraph.com) set(CPACK_DEBIAN_PACKAGE_HOMEPAGE https://memgraph.com)
set(CPACK_DEBIAN_PACKAGE_VERSION "${MEMGRAPH_VERSION_DEB}") set(CPACK_DEBIAN_PACKAGE_VERSION "${MEMGRAPH_VERSION_DEB}")
set(CPACK_DEBIAN_FILE_NAME "memgraph_${MEMGRAPH_VERSION_DEB}_${MG_ARCH_EXTENSION_DEB}.deb") set(CPACK_DEBIAN_FILE_NAME "memgraph_${MEMGRAPH_VERSION_DEB}_amd64.deb")
set(CPACK_DEBIAN_PACKAGE_CONTROL_EXTRA set(CPACK_DEBIAN_PACKAGE_CONTROL_EXTRA
"${CMAKE_CURRENT_SOURCE_DIR}/debian/conffiles;" "${CMAKE_CURRENT_SOURCE_DIR}/debian/conffiles;"
"${CMAKE_CURRENT_SOURCE_DIR}/debian/copyright;" "${CMAKE_CURRENT_SOURCE_DIR}/debian/copyright;"
@@ -41,20 +33,21 @@ set(CPACK_DEBIAN_PACKAGE_DESCRIPTION "${CPACK_PACKAGE_DESCRIPTION_SUMMARY}
applications driver by real-time connected data.") applications driver by real-time connected data.")
# Add `openssl` package to dependencies list. Used to generate SSL certificates. # Add `openssl` package to dependencies list. Used to generate SSL certificates.
# We also depend on `python3` because we embed it in Memgraph. # We also depend on `python3` because we embed it in Memgraph.
set(CPACK_DEBIAN_PACKAGE_DEPENDS "openssl (>= 1.1.0), python3 (>= 3.5.0), libstdc++6") set(CPACK_DEBIAN_PACKAGE_DEPENDS "openssl (>= 1.1.0), python3 (>= 3.5.0)")
# Setting arhitecture extension for rpm packages
set(MG_ARCH_EXTENSION_RPM "noarch")
if (${MG_ARCH} STREQUAL "x86_64")
set(MG_ARCH_EXTENSION_RPM "x86_64")
elseif (${MG_ARCH} STREQUAL "ARM64")
set(MG_ARCH_EXTENSION_RPM "aarch64")
endif()
# RPM specific # RPM specific
set(MG_ARCH_EXTENSION "noarch")
if (${MG_ARCH} STREQUAL "x86_64")
set(MG_ARCH_EXTENSION "x86_64")
elseif (${MG_ARCH} STREQUAL "ARM64")
set(MG_ARCH_EXTENSION "aarch64")
endif()
set(CPACK_RPM_PACKAGE_URL https://memgraph.com) set(CPACK_RPM_PACKAGE_URL https://memgraph.com)
set(CPACK_RPM_PACKAGE_VERSION "${MEMGRAPH_VERSION_RPM}") set(CPACK_RPM_PACKAGE_VERSION "${MEMGRAPH_VERSION_RPM}")
set(CPACK_RPM_FILE_NAME "memgraph-${MEMGRAPH_VERSION_RPM}-1.${MG_ARCH_EXTENSION_RPM}.rpm") set(CPACK_RPM_FILE_NAME "memgraph-${MEMGRAPH_VERSION_RPM}-1.${MG_ARCH_EXTENSION}.rpm")
set(CPACK_RPM_EXCLUDE_FROM_AUTO_FILELIST_ADDITION set(CPACK_RPM_EXCLUDE_FROM_AUTO_FILELIST_ADDITION
/var /var/lib /var/log /etc/logrotate.d /var /var/lib /var/log /etc/logrotate.d
/lib /lib/systemd /lib/systemd/system /lib/systemd/system/memgraph.service) /lib /lib/systemd /lib/systemd/system /lib/systemd/system/memgraph.service)
@@ -67,7 +60,7 @@ It aims to deliver developers the speed, simplicity and scale required to build
the next generation of applications driver by real-time connected data.") the next generation of applications driver by real-time connected data.")
# Add `openssl` package to dependencies list. Used to generate SSL certificates. # Add `openssl` package to dependencies list. Used to generate SSL certificates.
# We also depend on `python3` because we embed it in Memgraph. # We also depend on `python3` because we embed it in Memgraph.
set(CPACK_RPM_PACKAGE_REQUIRES "openssl >= 1.0.0, curl >= 7.29.0, python3 >= 3.5.0, libstdc >= 6, logrotate") set(CPACK_RPM_PACKAGE_REQUIRES "openssl >= 1.0.0, curl >= 7.29.0, python3 >= 3.5.0")
# All variables must be set before including. # All variables must be set before including.
include(CPack) include(CPack)

View File

@@ -1,21 +1,19 @@
FROM debian:bullseye FROM debian:bullseye
# NOTE: If you change the base distro update release/package as well. # NOTE: If you change the base distro update release/package as well.
ARG BINARY_NAME ARG release
ARG EXTENSION
ARG TARGETARCH
RUN apt-get update && apt-get install -y \ RUN apt-get update && apt-get install -y \
openssl libcurl4 libssl1.1 libseccomp2 python3 libpython3.9 python3-pip \ openssl libcurl4 libssl1.1 libseccomp2 python3 libpython3.9 python3-pip \
--no-install-recommends \ --no-install-recommends \
&& rm -rf /var/lib/apt/lists/* /tmp/* /var/tmp/* && rm -rf /var/lib/apt/lists/* /tmp/* /var/tmp/*
RUN pip3 install networkx==2.4 numpy==1.21.4 scipy==1.7.3 RUN pip3 install networkx==2.4 numpy==1.21.4 scipy==1.7.3
COPY "${BINARY_NAME}${TARGETARCH}.${EXTENSION}" / COPY ${release} /
# Install memgraph package # Install memgraph package
RUN dpkg -i "${BINARY_NAME}${TARGETARCH}.deb" RUN dpkg -i ${release}
# Memgraph listens for Bolt Protocol on this port by default. # Memgraph listens for Bolt Protocol on this port by default.
EXPOSE 7687 EXPOSE 7687

View File

@@ -0,0 +1,31 @@
FROM dokken/centos-stream-9
# NOTE: If you change the base distro update release/package as well.
ARG release
RUN yum update && yum install -y \
openssl libcurl libseccomp python3 python3-pip \
--nobest --allowerasing \
&& rm -rf /tmp/* \
&& yum clean all
RUN pip3 install networkx==2.4 numpy==1.21.4 scipy==1.7.3
COPY ${release} /
# Install memgraph package
RUN rpm -i ${release}
# Memgraph listens for Bolt Protocol on this port by default.
EXPOSE 7687
# Snapshots and logging volumes
VOLUME /var/log/memgraph
VOLUME /var/lib/memgraph
# Configuration volume
VOLUME /etc/memgraph
USER memgraph
WORKDIR /usr/lib/memgraph
ENTRYPOINT ["/usr/lib/memgraph/memgraph"]
CMD [""]

View File

@@ -55,10 +55,7 @@ image_name="memgraph:${version}"
image_package_name="memgraph-${version}-docker.tar.gz" image_package_name="memgraph-${version}-docker.tar.gz"
# Build docker image. # Build docker image.
docker build -t ${image_name} ${tag_latest} -f ${dockerfile_path} \ docker build -t ${image_name} ${tag_latest} -f ${dockerfile_path} --build-arg release=${package_name}.${extension} .
--build-arg BINARY_NAME=${package_name} \
--build-arg EXTENSION=${extension} \
--build-arg TARGETARCH="" .
docker save ${image_name} ${latest_image} | gzip > ${image_package_name} docker save ${image_name} ${latest_image} | gzip > ${image_package_name}
rm "${package_name}.${extension}" rm "${package_name}.${extension}"
echo "Built Docker image at '${working_dir}/${image_package_name}'" echo "Built Docker image at '${working_dir}/${image_package_name}'"

View File

@@ -104,9 +104,7 @@ def retry(retry_limit, timeout=100):
except Exception: except Exception:
time.sleep(timeout) time.sleep(timeout)
return func(*args, **kwargs) return func(*args, **kwargs)
return wrapper return wrapper
return inner_func return inner_func
@@ -165,15 +163,8 @@ def format_version(variant, version, offering, distance=None, shorthash=None, su
# Parse arguments. # Parse arguments.
parser = argparse.ArgumentParser(description="Get the current version of Memgraph.") parser = argparse.ArgumentParser(description="Get the current version of Memgraph.")
parser.add_argument( parser.add_argument("--open-source", action="store_true", help="set the current offering to 'open-source'")
"--open-source", parser.add_argument("version", help="manual version override, if supplied the version isn't " "determined using git")
action="store_true",
help="set the current offering to 'open-source'",
)
parser.add_argument(
"version",
help="manual version override, if supplied the version isn't " "determined using git",
)
parser.add_argument("suffix", help="custom suffix for the current version being built") parser.add_argument("suffix", help="custom suffix for the current version being built")
parser.add_argument( parser.add_argument(
"--variant", "--variant",
@@ -182,9 +173,7 @@ parser.add_argument(
help="which variant of the version string should be generated", help="which variant of the version string should be generated",
) )
parser.add_argument( parser.add_argument(
"--memgraph-root-dir", "--memgraph-root-dir", help="The root directory of the checked out " "Memgraph repository.", default="."
help="The root directory of the checked out " "Memgraph repository.",
default=".",
) )
args = parser.parse_args() args = parser.parse_args()
@@ -267,27 +256,14 @@ for version in versions:
if current_version is None: if current_version is None:
raise Exception("You are attempting to determine the version for a very " "old version of Memgraph!") raise Exception("You are attempting to determine the version for a very " "old version of Memgraph!")
version, branch, master_branch_merge = current_version version, branch, master_branch_merge = current_version
distance = int( distance = int(get_output("git", "rev-list", "--count", "--first-parent", master_branch_merge + ".." + current_hash))
get_output(
"git",
"rev-list",
"--count",
"--first-parent",
master_branch_merge + ".." + current_hash,
)
)
version_str = ".".join(map(str, version)) + ".0" version_str = ".".join(map(str, version)) + ".0"
if distance == 0: if distance == 0:
print(format_version(args.variant, version_str, offering, suffix=args.suffix), end="") print(format_version(args.variant, version_str, offering, suffix=args.suffix), end="")
else: else:
print( print(
format_version( format_version(
args.variant, args.variant, version_str, offering, distance=distance, shorthash=current_hash_short, suffix=args.suffix
version_str,
offering,
distance=distance,
shorthash=current_hash_short,
suffix=args.suffix,
), ),
end="", end="",
) )

View File

@@ -7,8 +7,8 @@ RUN yum -y update \
# Do NOT be smart here and clean the cache because the container is used in the # Do NOT be smart here and clean the cache because the container is used in the
# stateful context. # stateful context.
RUN wget -q https://s3-eu-west-1.amazonaws.com/deps.memgraph.io/${TOOLCHAIN_VERSION}/${TOOLCHAIN_VERSION}-binaries-centos-7-x86_64.tar.gz \ RUN wget -q https://s3-eu-west-1.amazonaws.com/deps.memgraph.io/${TOOLCHAIN_VERSION}/${TOOLCHAIN_VERSION}-binaries-centos-7.tar.gz \
-O ${TOOLCHAIN_VERSION}-binaries-centos-7-x86_64.tar.gz \ -O ${TOOLCHAIN_VERSION}-binaries-centos-7.tar.gz \
&& tar xzvf ${TOOLCHAIN_VERSION}-binaries-centos-7-x86_64.tar.gz -C /opt && tar xzvf ${TOOLCHAIN_VERSION}-binaries-centos-7.tar.gz -C /opt
ENTRYPOINT ["sleep", "infinity"] ENTRYPOINT ["sleep", "infinity"]

View File

@@ -0,0 +1,14 @@
FROM centos:8
ARG TOOLCHAIN_VERSION
RUN dnf -y update \
&& dnf install -y wget git
# Do NOT be smart here and clean the cache because the container is used in the
# stateful context.
RUN wget -q https://s3-eu-west-1.amazonaws.com/deps.memgraph.io/${TOOLCHAIN_VERSION}/${TOOLCHAIN_VERSION}-binaries-centos-8.tar.gz \
-O ${TOOLCHAIN_VERSION}-binaries-centos-8.tar.gz \
&& tar xzvf ${TOOLCHAIN_VERSION}-binaries-centos-8.tar.gz -C /opt
ENTRYPOINT ["sleep", "infinity"]

View File

@@ -1,14 +0,0 @@
FROM quay.io/centos/centos:stream9
ARG TOOLCHAIN_VERSION
RUN yum -y update \
&& yum install -y wget git
# Do NOT be smart here and clean the cache because the container is used in the
# stateful context.
RUN wget -q https://s3-eu-west-1.amazonaws.com/deps.memgraph.io/${TOOLCHAIN_VERSION}/${TOOLCHAIN_VERSION}-binaries-centos-9-x86_64.tar.gz \
-O ${TOOLCHAIN_VERSION}-binaries-centos-9-x86_64.tar.gz \
&& tar xzvf ${TOOLCHAIN_VERSION}-binaries-centos-9-x86_64.tar.gz -C /opt
ENTRYPOINT ["sleep", "infinity"]

View File

@@ -10,8 +10,8 @@ RUN apt update && apt install -y \
# Do NOT be smart here and clean the cache because the container is used in the # Do NOT be smart here and clean the cache because the container is used in the
# stateful context. # stateful context.
RUN wget -q https://s3-eu-west-1.amazonaws.com/deps.memgraph.io/${TOOLCHAIN_VERSION}/${TOOLCHAIN_VERSION}-binaries-debian-10-amd64.tar.gz \ RUN wget -q https://s3-eu-west-1.amazonaws.com/deps.memgraph.io/${TOOLCHAIN_VERSION}/${TOOLCHAIN_VERSION}-binaries-debian-10.tar.gz \
-O ${TOOLCHAIN_VERSION}-binaries-debian-10-amd64.tar.gz \ -O ${TOOLCHAIN_VERSION}-binaries-debian-10.tar.gz \
&& tar xzvf ${TOOLCHAIN_VERSION}-binaries-debian-10-amd64.tar.gz -C /opt && tar xzvf ${TOOLCHAIN_VERSION}-binaries-debian-10.tar.gz -C /opt
ENTRYPOINT ["sleep", "infinity"] ENTRYPOINT ["sleep", "infinity"]

View File

@@ -1,17 +0,0 @@
FROM debian:11
ARG TOOLCHAIN_VERSION
# Stops tzdata interactive configuration.
ENV DEBIAN_FRONTEND=noninteractive
RUN apt update && apt install -y \
ca-certificates wget git
# Do NOT be smart here and clean the cache because the container is used in the
# stateful context.
RUN wget -q https://s3-eu-west-1.amazonaws.com/deps.memgraph.io/${TOOLCHAIN_VERSION}/${TOOLCHAIN_VERSION}-binaries-debian-11-arm64.tar.gz \
-O ${TOOLCHAIN_VERSION}-binaries-debian-11-arm64.tar.gz \
&& tar xzvf ${TOOLCHAIN_VERSION}-binaries-debian-11-arm64.tar.gz -C /opt
ENTRYPOINT ["sleep", "infinity"]

View File

@@ -10,8 +10,8 @@ RUN apt update && apt install -y \
# Do NOT be smart here and clean the cache because the container is used in the # Do NOT be smart here and clean the cache because the container is used in the
# stateful context. # stateful context.
RUN wget -q https://s3-eu-west-1.amazonaws.com/deps.memgraph.io/${TOOLCHAIN_VERSION}/${TOOLCHAIN_VERSION}-binaries-debian-11-amd64.tar.gz \ RUN wget -q https://s3-eu-west-1.amazonaws.com/deps.memgraph.io/${TOOLCHAIN_VERSION}/${TOOLCHAIN_VERSION}-binaries-debian-11.tar.gz \
-O ${TOOLCHAIN_VERSION}-binaries-debian-11-amd64.tar.gz \ -O ${TOOLCHAIN_VERSION}-binaries-debian-11.tar.gz \
&& tar xzvf ${TOOLCHAIN_VERSION}-binaries-debian-11-amd64.tar.gz -C /opt && tar xzvf ${TOOLCHAIN_VERSION}-binaries-debian-11.tar.gz -C /opt
ENTRYPOINT ["sleep", "infinity"] ENTRYPOINT ["sleep", "infinity"]

View File

@@ -4,10 +4,10 @@ services:
build: build:
context: centos-7 context: centos-7
container_name: "mgbuild_centos-7" container_name: "mgbuild_centos-7"
mgbuild_centos-9: mgbuild_centos-8:
build: build:
context: centos-9 context: centos-8
container_name: "mgbuild_centos-9" container_name: "mgbuild_centos-8"
mgbuild_debian-10: mgbuild_debian-10:
build: build:
context: debian-10 context: debian-10
@@ -24,7 +24,3 @@ services:
build: build:
context: ubuntu-20.04 context: ubuntu-20.04
container_name: "mgbuild_ubuntu-20.04" container_name: "mgbuild_ubuntu-20.04"
mgbuild_ubuntu-22.04:
build:
context: ubuntu-22.04
container_name: "mgbuild_ubuntu-22.04"

View File

@@ -3,7 +3,7 @@
set -Eeuo pipefail set -Eeuo pipefail
SCRIPT_DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )" SCRIPT_DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )"
SUPPORTED_OS=(centos-7 centos-9 debian-10 debian-11 ubuntu-18.04 ubuntu-20.04 ubuntu-22.04 debian-11-arm) SUPPORTED_OS=(centos-7 centos-8 debian-10 debian-11 ubuntu-18.04 ubuntu-20.04)
PROJECT_ROOT="$SCRIPT_DIR/../.." PROJECT_ROOT="$SCRIPT_DIR/../.."
TOOLCHAIN_VERSION="toolchain-v4" TOOLCHAIN_VERSION="toolchain-v4"
ACTIVATE_TOOLCHAIN="source /opt/${TOOLCHAIN_VERSION}/activate" ACTIVATE_TOOLCHAIN="source /opt/${TOOLCHAIN_VERSION}/activate"
@@ -67,18 +67,14 @@ make_package () {
# environment/os/{os}.sh does not come within the toolchain package. When # environment/os/{os}.sh does not come within the toolchain package. When
# migrating to the next version of toolchain do that, and remove the # migrating to the next version of toolchain do that, and remove the
# TOOLCHAIN_RUN_DEPS installation from here. # TOOLCHAIN_RUN_DEPS installation from here.
echo "Installing dependencies using '/memgraph/environment/os/$os.sh' script..." echo "Installing dependencies..."
docker exec "$build_container" bash -c "/memgraph/environment/os/$os.sh install TOOLCHAIN_RUN_DEPS" docker exec "$build_container" bash -c "/memgraph/environment/os/$os.sh install TOOLCHAIN_RUN_DEPS"
docker exec "$build_container" bash -c "/memgraph/environment/os/$os.sh install MEMGRAPH_BUILD_DEPS" docker exec "$build_container" bash -c "/memgraph/environment/os/$os.sh install MEMGRAPH_BUILD_DEPS"
echo "Building targeted package..." echo "Building targeted package..."
docker exec "$build_container" bash -c "cd /memgraph && $ACTIVATE_TOOLCHAIN && ./init" docker exec "$build_container" bash -c "cd /memgraph && $ACTIVATE_TOOLCHAIN && ./init"
docker exec "$build_container" bash -c "cd $container_build_dir && rm -rf ./*" docker exec "$build_container" bash -c "cd $container_build_dir && rm -rf ./*"
if [[ "$os" == "debian-11-arm" ]]; then docker exec "$build_container" bash -c "cd $container_build_dir && $ACTIVATE_TOOLCHAIN && cmake -DCMAKE_BUILD_TYPE=release $telemetry_id_override_flag .."
docker exec "$build_container" bash -c "cd $container_build_dir && $ACTIVATE_TOOLCHAIN && cmake -DCMAKE_BUILD_TYPE=release -DMG_ARCH="ARM64" $telemetry_id_override_flag .."
else
docker exec "$build_container" bash -c "cd $container_build_dir && $ACTIVATE_TOOLCHAIN && cmake -DCMAKE_BUILD_TYPE=release $telemetry_id_override_flag .."
fi
# ' is used instead of " because we need to run make within the allowed # ' is used instead of " because we need to run make within the allowed
# container resources. # container resources.
# shellcheck disable=SC2016 # shellcheck disable=SC2016

View File

@@ -10,8 +10,8 @@ RUN apt update && apt install -y \
# Do NOT be smart here and clean the cache because the container is used in the # Do NOT be smart here and clean the cache because the container is used in the
# stateful context. # stateful context.
RUN wget -q https://s3-eu-west-1.amazonaws.com/deps.memgraph.io/${TOOLCHAIN_VERSION}/${TOOLCHAIN_VERSION}-binaries-ubuntu-18.04-amd64.tar.gz \ RUN wget -q https://s3-eu-west-1.amazonaws.com/deps.memgraph.io/${TOOLCHAIN_VERSION}/${TOOLCHAIN_VERSION}-binaries-ubuntu-18.04.tar.gz \
-O ${TOOLCHAIN_VERSION}-binaries-ubuntu-18.04-amd64.tar.gz \ -O ${TOOLCHAIN_VERSION}-binaries-ubuntu-18.04.tar.gz \
&& tar xzvf ${TOOLCHAIN_VERSION}-binaries-ubuntu-18.04-amd64.tar.gz -C /opt && tar xzvf ${TOOLCHAIN_VERSION}-binaries-ubuntu-18.04.tar.gz -C /opt
ENTRYPOINT ["sleep", "infinity"] ENTRYPOINT ["sleep", "infinity"]

View File

@@ -10,8 +10,8 @@ RUN apt update && apt install -y \
# Do NOT be smart here and clean the cache because the container is used in the # Do NOT be smart here and clean the cache because the container is used in the
# stateful context. # stateful context.
RUN wget -q https://s3-eu-west-1.amazonaws.com/deps.memgraph.io/${TOOLCHAIN_VERSION}/${TOOLCHAIN_VERSION}-binaries-ubuntu-20.04-amd64.tar.gz \ RUN wget -q https://s3-eu-west-1.amazonaws.com/deps.memgraph.io/${TOOLCHAIN_VERSION}/${TOOLCHAIN_VERSION}-binaries-ubuntu-20.04.tar.gz \
-O ${TOOLCHAIN_VERSION}-binaries-ubuntu-20.04-amd64.tar.gz \ -O ${TOOLCHAIN_VERSION}-binaries-ubuntu-20.04.tar.gz \
&& tar xzvf ${TOOLCHAIN_VERSION}-binaries-ubuntu-20.04-amd64.tar.gz -C /opt && tar xzvf ${TOOLCHAIN_VERSION}-binaries-ubuntu-20.04.tar.gz -C /opt
ENTRYPOINT ["sleep", "infinity"] ENTRYPOINT ["sleep", "infinity"]

View File

@@ -1,17 +0,0 @@
FROM ubuntu:22.04
ARG TOOLCHAIN_VERSION
# Stops tzdata interactive configuration.
ENV DEBIAN_FRONTEND=noninteractive
RUN apt update && apt install -y \
ca-certificates wget git
# Do NOT be smart here and clean the cache because the container is used in the
# stateful context.
RUN wget -q https://s3-eu-west-1.amazonaws.com/deps.memgraph.io/${TOOLCHAIN_VERSION}/${TOOLCHAIN_VERSION}-binaries-ubuntu-22.04-amd64.tar.gz \
-O ${TOOLCHAIN_VERSION}-binaries-ubuntu-22.04-amd64.tar.gz \
&& tar xzvf ${TOOLCHAIN_VERSION}-binaries-ubuntu-22.04-amd64.tar.gz -C /opt
ENTRYPOINT ["sleep", "infinity"]

View File

@@ -1,4 +1,4 @@
// Copyright 2022 Memgraph Ltd. // Copyright 2021 Memgraph Ltd.
// //
// Licensed as a Memgraph Enterprise file under the Memgraph Enterprise // Licensed as a Memgraph Enterprise file under the Memgraph Enterprise
// License (the "License"); by using this file, you agree to be bound by the terms of the License, and you may not use // License (the "License"); by using this file, you agree to be bound by the terms of the License, and you may not use
@@ -18,7 +18,7 @@
#include "utils/logging.hpp" #include "utils/logging.hpp"
#include "utils/string.hpp" #include "utils/string.hpp"
namespace memgraph::audit { namespace audit {
// Helper function that converts a `storage::PropertyValue` to `nlohmann::json`. // Helper function that converts a `storage::PropertyValue` to `nlohmann::json`.
inline nlohmann::json PropertyValueToJson(const storage::PropertyValue &pv) { inline nlohmann::json PropertyValueToJson(const storage::PropertyValue &pv) {
@@ -143,4 +143,4 @@ void Log::Flush() {
log_.Sync(); log_.Sync();
} }
} // namespace memgraph::audit } // namespace audit

View File

@@ -1,4 +1,4 @@
// Copyright 2022 Memgraph Ltd. // Copyright 2021 Memgraph Ltd.
// //
// Licensed as a Memgraph Enterprise file under the Memgraph Enterprise // Licensed as a Memgraph Enterprise file under the Memgraph Enterprise
// License (the "License"); by using this file, you agree to be bound by the terms of the License, and you may not use // License (the "License"); by using this file, you agree to be bound by the terms of the License, and you may not use
@@ -17,7 +17,7 @@
#include "utils/file.hpp" #include "utils/file.hpp"
#include "utils/scheduler.hpp" #include "utils/scheduler.hpp"
namespace memgraph::audit { namespace audit {
const uint64_t kBufferSizeDefault = 100000; const uint64_t kBufferSizeDefault = 100000;
const uint64_t kBufferFlushIntervalMillisDefault = 200; const uint64_t kBufferFlushIntervalMillisDefault = 200;
@@ -71,4 +71,4 @@ class Log {
std::mutex lock_; std::mutex lock_;
}; };
} // namespace memgraph::audit } // namespace audit

View File

@@ -11,7 +11,7 @@ find_package(gflags REQUIRED)
add_library(mg-auth STATIC ${auth_src_files}) add_library(mg-auth STATIC ${auth_src_files})
target_link_libraries(mg-auth json libbcrypt gflags fmt::fmt) target_link_libraries(mg-auth json libbcrypt gflags fmt::fmt)
target_link_libraries(mg-auth mg-utils mg-kvstore mg-license ) target_link_libraries(mg-auth mg-utils mg-kvstore)
target_link_libraries(mg-auth ${Seccomp_LIBRARIES}) target_link_libraries(mg-auth ${Seccomp_LIBRARIES})
target_include_directories(mg-auth SYSTEM PRIVATE ${Seccomp_INCLUDE_DIRS}) target_include_directories(mg-auth SYSTEM PRIVATE ${Seccomp_INCLUDE_DIRS})

View File

@@ -1,4 +1,4 @@
// Copyright 2022 Memgraph Ltd. // Copyright 2021 Memgraph Ltd.
// //
// Licensed as a Memgraph Enterprise file under the Memgraph Enterprise // Licensed as a Memgraph Enterprise file under the Memgraph Enterprise
// License (the "License"); by using this file, you agree to be bound by the terms of the License, and you may not use // License (the "License"); by using this file, you agree to be bound by the terms of the License, and you may not use
@@ -42,7 +42,8 @@ DEFINE_VALIDATED_int32(auth_module_timeout_ms, 10000,
"response from the auth module.", "response from the auth module.",
FLAG_IN_RANGE(100, 1800000)); FLAG_IN_RANGE(100, 1800000));
namespace memgraph::auth { namespace auth {
const std::string kUserPrefix = "user:"; const std::string kUserPrefix = "user:";
const std::string kRolePrefix = "role:"; const std::string kRolePrefix = "role:";
const std::string kLinkPrefix = "link:"; const std::string kLinkPrefix = "link:";
@@ -315,4 +316,4 @@ std::vector<auth::User> Auth::AllUsersForRole(const std::string &rolename_orig)
return ret; return ret;
} }
} // namespace memgraph::auth } // namespace auth

View File

@@ -1,4 +1,4 @@
// Copyright 2022 Memgraph Ltd. // Copyright 2021 Memgraph Ltd.
// //
// Licensed as a Memgraph Enterprise file under the Memgraph Enterprise // Licensed as a Memgraph Enterprise file under the Memgraph Enterprise
// License (the "License"); by using this file, you agree to be bound by the terms of the License, and you may not use // License (the "License"); by using this file, you agree to be bound by the terms of the License, and you may not use
@@ -18,7 +18,8 @@
#include "kvstore/kvstore.hpp" #include "kvstore/kvstore.hpp"
#include "utils/settings.hpp" #include "utils/settings.hpp"
namespace memgraph::auth { namespace auth {
/** /**
* This class serves as the main Authentication/Authorization storage. * This class serves as the main Authentication/Authorization storage.
* It provides functions for managing Users, Roles and Permissions. * It provides functions for managing Users, Roles and Permissions.
@@ -162,4 +163,4 @@ class Auth final {
kvstore::KVStore storage_; kvstore::KVStore storage_;
auth::Module module_; auth::Module module_;
}; };
} // namespace memgraph::auth } // namespace auth

View File

@@ -1,4 +1,4 @@
// Copyright 2022 Memgraph Ltd. // Copyright 2021 Memgraph Ltd.
// //
// Licensed as a Memgraph Enterprise file under the Memgraph Enterprise // Licensed as a Memgraph Enterprise file under the Memgraph Enterprise
// License (the "License"); by using this file, you agree to be bound by the terms of the License, and you may not use // License (the "License"); by using this file, you agree to be bound by the terms of the License, and you may not use
@@ -12,7 +12,8 @@
#include "auth/exceptions.hpp" #include "auth/exceptions.hpp"
namespace memgraph::auth { namespace auth {
const std::string EncryptPassword(const std::string &password) { const std::string EncryptPassword(const std::string &password) {
char salt[BCRYPT_HASHSIZE]; char salt[BCRYPT_HASHSIZE];
char hash[BCRYPT_HASHSIZE]; char hash[BCRYPT_HASHSIZE];
@@ -39,4 +40,4 @@ bool VerifyPassword(const std::string &password, const std::string &hash) {
return ret == 0; return ret == 0;
} }
} // namespace memgraph::auth } // namespace auth

View File

@@ -1,4 +1,4 @@
// Copyright 2022 Memgraph Ltd. // Copyright 2021 Memgraph Ltd.
// //
// Licensed as a Memgraph Enterprise file under the Memgraph Enterprise // Licensed as a Memgraph Enterprise file under the Memgraph Enterprise
// License (the "License"); by using this file, you agree to be bound by the terms of the License, and you may not use // License (the "License"); by using this file, you agree to be bound by the terms of the License, and you may not use
@@ -10,11 +10,12 @@
#include <string> #include <string>
namespace memgraph::auth { namespace auth {
/// @throw AuthException if unable to encrypt the password. /// @throw AuthException if unable to encrypt the password.
const std::string EncryptPassword(const std::string &password); const std::string EncryptPassword(const std::string &password);
/// @throw AuthException if unable to verify the password. /// @throw AuthException if unable to verify the password.
bool VerifyPassword(const std::string &password, const std::string &hash); bool VerifyPassword(const std::string &password, const std::string &hash);
} // namespace memgraph::auth } // namespace auth

View File

@@ -1,4 +1,4 @@
// Copyright 2022 Memgraph Ltd. // Copyright 2021 Memgraph Ltd.
// //
// Use of this software is governed by the Business Source License // Use of this software is governed by the Business Source License
// included in the file licenses/BSL.txt; by using this file, you agree to be bound by the terms of the Business Source // included in the file licenses/BSL.txt; by using this file, you agree to be bound by the terms of the Business Source
@@ -13,7 +13,8 @@
#include "utils/exceptions.hpp" #include "utils/exceptions.hpp"
namespace memgraph::auth { namespace auth {
/** /**
* This exception class is thrown for all exceptions that can occur when dealing * This exception class is thrown for all exceptions that can occur when dealing
* with the Auth library. * with the Auth library.
@@ -22,4 +23,4 @@ class AuthException : public utils::BasicException {
public: public:
using utils::BasicException::BasicException; using utils::BasicException::BasicException;
}; };
} // namespace memgraph::auth } // namespace auth

View File

@@ -1,4 +1,4 @@
// Copyright 2022 Memgraph Ltd. // Copyright 2021 Memgraph Ltd.
// //
// Licensed as a Memgraph Enterprise file under the Memgraph Enterprise // Licensed as a Memgraph Enterprise file under the Memgraph Enterprise
// License (the "License"); by using this file, you agree to be bound by the terms of the License, and you may not use // License (the "License"); by using this file, you agree to be bound by the terms of the License, and you may not use
@@ -22,23 +22,13 @@
// NOLINTNEXTLINE(cppcoreguidelines-avoid-non-const-global-variables) // NOLINTNEXTLINE(cppcoreguidelines-avoid-non-const-global-variables)
DEFINE_bool(auth_password_permit_null, true, "Set to false to disable null passwords."); DEFINE_bool(auth_password_permit_null, true, "Set to false to disable null passwords.");
inline constexpr std::string_view default_password_regex = ".+"; constexpr std::string_view default_password_regex = ".+";
// NOLINTNEXTLINE(cppcoreguidelines-avoid-non-const-global-variables) // NOLINTNEXTLINE(cppcoreguidelines-avoid-non-const-global-variables)
DEFINE_string(auth_password_strength_regex, default_password_regex.data(), DEFINE_string(auth_password_strength_regex, default_password_regex.data(),
"The regular expression that should be used to match the entire " "The regular expression that should be used to match the entire "
"entered password to ensure its strength."); "entered password to ensure its strength.");
namespace memgraph::auth { namespace auth {
namespace {
// Constant list of all available permissions.
const std::vector<Permission> kPermissionsAll = {
Permission::MATCH, Permission::CREATE, Permission::MERGE, Permission::DELETE,
Permission::SET, Permission::REMOVE, Permission::INDEX, Permission::STATS,
Permission::CONSTRAINT, Permission::DUMP, Permission::AUTH, Permission::REPLICATION,
Permission::DURABILITY, Permission::READ_FILE, Permission::FREE_MEMORY, Permission::TRIGGER,
Permission::CONFIG, Permission::STREAM, Permission::MODULE_READ, Permission::MODULE_WRITE,
Permission::WEBSOCKET};
} // namespace
std::string PermissionToString(Permission permission) { std::string PermissionToString(Permission permission) {
switch (permission) { switch (permission) {
@@ -78,14 +68,6 @@ std::string PermissionToString(Permission permission) {
return "AUTH"; return "AUTH";
case Permission::STREAM: case Permission::STREAM:
return "STREAM"; return "STREAM";
case Permission::MODULE_READ:
return "MODULE_READ";
case Permission::MODULE_WRITE:
return "MODULE_WRITE";
case Permission::WEBSOCKET:
return "WEBSOCKET";
case Permission::LABELS:
return "LABELS";
} }
} }
@@ -185,107 +167,19 @@ bool operator==(const Permissions &first, const Permissions &second) {
bool operator!=(const Permissions &first, const Permissions &second) { return !(first == second); } bool operator!=(const Permissions &first, const Permissions &second) { return !(first == second); }
LabelPermissions::LabelPermissions(const std::unordered_set<std::string> &grants,
const std::unordered_set<std::string> &denies)
: grants_(grants), denies_(denies) {}
PermissionLevel LabelPermissions::Has(const std::string &permission) const {
if (denies_.find(permission) != denies_.end()) {
return PermissionLevel::DENY;
}
if (grants_.find(permission) != denies_.end()) {
return PermissionLevel::GRANT;
}
return PermissionLevel::NEUTRAL;
}
void LabelPermissions::Grant(const std::string &permission) {
auto deniedPermissionIter = denies_.find(permission);
if (deniedPermissionIter != denies_.end()) {
denies_.erase(deniedPermissionIter);
}
if (grants_.find(permission) == grants_.end()) {
grants_.insert(permission);
}
}
void LabelPermissions::Revoke(const std::string &permission) {
auto deniedPermissionIter = denies_.find(permission);
auto grantedPermissionIter = grants_.find(permission);
if (deniedPermissionIter != denies_.end()) {
denies_.erase(deniedPermissionIter);
}
if (grantedPermissionIter != grants_.end()) {
grants_.erase(grantedPermissionIter);
}
}
void LabelPermissions::Deny(const std::string &permission) {
auto grantedPermissionIter = grants_.find(permission);
if (grantedPermissionIter != grants_.end()) {
grants_.erase(grantedPermissionIter);
}
if (denies_.find(permission) == denies_.end()) {
denies_.insert(permission);
}
}
std::unordered_set<std::string> LabelPermissions::GetGrants() const { return grants_; }
std::unordered_set<std::string> LabelPermissions::GetDenies() const { return denies_; }
nlohmann::json LabelPermissions::Serialize() const {
nlohmann::json data = nlohmann::json::object();
data["grants"] = grants_;
data["denies"] = denies_;
return data;
}
LabelPermissions LabelPermissions::Deserialize(const nlohmann::json &data) {
if (!data.is_object()) {
throw AuthException("Couldn't load permissions data!");
}
return {LabelPermissions(data["grants"], data["denies"])};
}
std::unordered_set<std::string> LabelPermissions::grants() const { return grants_; }
std::unordered_set<std::string> LabelPermissions::denies() const { return denies_; }
bool operator==(const LabelPermissions &first, const LabelPermissions &second) {
return first.grants() == second.grants() && first.denies() == second.denies();
}
bool operator!=(const LabelPermissions &first, const LabelPermissions &second) { return !(first == second); }
Role::Role(const std::string &rolename) : rolename_(utils::ToLowerCase(rolename)) {} Role::Role(const std::string &rolename) : rolename_(utils::ToLowerCase(rolename)) {}
Role::Role(const std::string &rolename, const Permissions &permissions) Role::Role(const std::string &rolename, const Permissions &permissions)
: rolename_(utils::ToLowerCase(rolename)), permissions_(permissions) {} : rolename_(utils::ToLowerCase(rolename)), permissions_(permissions) {}
Role::Role(const std::string &rolename, const Permissions &permissions, const LabelPermissions &labelPermissions)
: rolename_(utils::ToLowerCase(rolename)), permissions_(permissions), labelPermissions_(labelPermissions) {}
const std::string &Role::rolename() const { return rolename_; } const std::string &Role::rolename() const { return rolename_; }
const Permissions &Role::permissions() const { return permissions_; } const Permissions &Role::permissions() const { return permissions_; }
Permissions &Role::permissions() { return permissions_; } Permissions &Role::permissions() { return permissions_; }
LabelPermissions &Role::labelPermissions() { return labelPermissions_; }
nlohmann::json Role::Serialize() const { nlohmann::json Role::Serialize() const {
nlohmann::json data = nlohmann::json::object(); nlohmann::json data = nlohmann::json::object();
data["rolename"] = rolename_; data["rolename"] = rolename_;
data["permissions"] = permissions_.Serialize(); data["permissions"] = permissions_.Serialize();
data["labelPermissions"] = labelPermissions_.Serialize();
return data; return data;
} }
@@ -297,9 +191,7 @@ Role Role::Deserialize(const nlohmann::json &data) {
throw AuthException("Couldn't load role data!"); throw AuthException("Couldn't load role data!");
} }
auto permissions = Permissions::Deserialize(data["permissions"]); auto permissions = Permissions::Deserialize(data["permissions"]);
auto labelPermissions = LabelPermissions::Deserialize(data["labelPermissions"]); return {data["rolename"], permissions};
return {data["rolename"], permissions, labelPermissions};
} }
bool operator==(const Role &first, const Role &second) { bool operator==(const Role &first, const Role &second) {
@@ -311,13 +203,6 @@ User::User(const std::string &username) : username_(utils::ToLowerCase(username)
User::User(const std::string &username, const std::string &password_hash, const Permissions &permissions) User::User(const std::string &username, const std::string &password_hash, const Permissions &permissions)
: username_(utils::ToLowerCase(username)), password_hash_(password_hash), permissions_(permissions) {} : username_(utils::ToLowerCase(username)), password_hash_(password_hash), permissions_(permissions) {}
User::User(const std::string &username, const std::string &password_hash, const Permissions &permissions,
const LabelPermissions &labelPermissions)
: username_(utils::ToLowerCase(username)),
password_hash_(password_hash),
permissions_(permissions),
labelPermissions_(labelPermissions) {}
bool User::CheckPassword(const std::string &password) { bool User::CheckPassword(const std::string &password) {
if (password_hash_.empty()) return true; if (password_hash_.empty()) return true;
return VerifyPassword(password, password_hash_); return VerifyPassword(password, password_hash_);
@@ -370,8 +255,6 @@ const std::string &User::username() const { return username_; }
const Permissions &User::permissions() const { return permissions_; } const Permissions &User::permissions() const { return permissions_; }
Permissions &User::permissions() { return permissions_; } Permissions &User::permissions() { return permissions_; }
LabelPermissions &User::labelPermissions() { return labelPermissions_; }
const Role *User::role() const { const Role *User::role() const {
if (role_.has_value()) { if (role_.has_value()) {
return &role_.value(); return &role_.value();
@@ -384,7 +267,6 @@ nlohmann::json User::Serialize() const {
data["username"] = username_; data["username"] = username_;
data["password_hash"] = password_hash_; data["password_hash"] = password_hash_;
data["permissions"] = permissions_.Serialize(); data["permissions"] = permissions_.Serialize();
data["labelPermissions"] = labelPermissions_.Serialize();
// The role shouldn't be serialized here, it is stored as a foreign key. // The role shouldn't be serialized here, it is stored as a foreign key.
return data; return data;
} }
@@ -397,14 +279,11 @@ User User::Deserialize(const nlohmann::json &data) {
throw AuthException("Couldn't load user data!"); throw AuthException("Couldn't load user data!");
} }
auto permissions = Permissions::Deserialize(data["permissions"]); auto permissions = Permissions::Deserialize(data["permissions"]);
auto labelPermissions = LabelPermissions::Deserialize(data["labelPermissions"]); return {data["username"], data["password_hash"], permissions};
return {data["username"], data["password_hash"], permissions, labelPermissions};
} }
bool operator==(const User &first, const User &second) { bool operator==(const User &first, const User &second) {
return first.username_ == second.username_ && first.password_hash_ == second.password_hash_ && return first.username_ == second.username_ && first.password_hash_ == second.password_hash_ &&
first.permissions_ == second.permissions_ && first.role_ == second.role_; first.permissions_ == second.permissions_ && first.role_ == second.role_;
} }
} // namespace auth
} // namespace memgraph::auth

View File

@@ -1,4 +1,4 @@
// Copyright 2022 Memgraph Ltd. // Copyright 2021 Memgraph Ltd.
// //
// Licensed as a Memgraph Enterprise file under the Memgraph Enterprise // Licensed as a Memgraph Enterprise file under the Memgraph Enterprise
// License (the "License"); by using this file, you agree to be bound by the terms of the License, and you may not use // License (the "License"); by using this file, you agree to be bound by the terms of the License, and you may not use
@@ -12,38 +12,42 @@
#include <string> #include <string>
#include <json/json.hpp> #include <json/json.hpp>
#include <unordered_set>
namespace memgraph::auth { namespace auth {
// These permissions must have values that are applicable for usage in a // These permissions must have values that are applicable for usage in a
// bitmask. // bitmask.
// clang-format off // clang-format off
enum class Permission : uint64_t { enum class Permission : uint64_t {
MATCH = 1, MATCH = 1,
CREATE = 1U << 1U, CREATE = 1U << 1U,
MERGE = 1U << 2U, MERGE = 1U << 2U,
DELETE = 1U << 3U, DELETE = 1U << 3U,
SET = 1U << 4U, SET = 1U << 4U,
REMOVE = 1U << 5U, REMOVE = 1U << 5U,
INDEX = 1U << 6U, INDEX = 1U << 6U,
STATS = 1U << 7U, STATS = 1U << 7U,
CONSTRAINT = 1U << 8U, CONSTRAINT = 1U << 8U,
DUMP = 1U << 9U, DUMP = 1U << 9U,
REPLICATION = 1U << 10U, REPLICATION = 1U << 10U,
DURABILITY = 1U << 11U, DURABILITY = 1U << 11U,
READ_FILE = 1U << 12U, READ_FILE = 1U << 12U,
FREE_MEMORY = 1U << 13U, FREE_MEMORY = 1U << 13U,
TRIGGER = 1U << 14U, TRIGGER = 1U << 14U,
CONFIG = 1U << 15U, CONFIG = 1U << 15U,
AUTH = 1U << 16U, AUTH = 1U << 16U,
STREAM = 1U << 17U, STREAM = 1U << 17U
MODULE_READ = 1U << 18U,
MODULE_WRITE = 1U << 19U,
WEBSOCKET = 1U << 20U,
LABELS = 1U << 21U
}; };
// clang-format on // clang-format on
// Constant list of all available permissions.
const std::vector<Permission> kPermissionsAll = {Permission::MATCH, Permission::CREATE, Permission::MERGE,
Permission::DELETE, Permission::SET, Permission::REMOVE,
Permission::INDEX, Permission::STATS, Permission::CONSTRAINT,
Permission::DUMP, Permission::AUTH, Permission::REPLICATION,
Permission::DURABILITY, Permission::READ_FILE, Permission::FREE_MEMORY,
Permission::TRIGGER, Permission::CONFIG, Permission::STREAM};
// Function that converts a permission to its string representation. // Function that converts a permission to its string representation.
std::string PermissionToString(Permission permission); std::string PermissionToString(Permission permission);
@@ -90,52 +94,16 @@ bool operator==(const Permissions &first, const Permissions &second);
bool operator!=(const Permissions &first, const Permissions &second); bool operator!=(const Permissions &first, const Permissions &second);
class LabelPermissions final {
public:
LabelPermissions(const std::unordered_set<std::string> &grants = {},
const std::unordered_set<std::string> &denies = {});
PermissionLevel Has(const std::string &permission) const;
void Grant(const std::string &permission);
void Revoke(const std::string &permission);
void Deny(const std::string &permission);
std::unordered_set<std::string> GetGrants() const;
std::unordered_set<std::string> GetDenies() const;
nlohmann::json Serialize() const;
/// @throw AuthException if unable to deserialize.
static LabelPermissions Deserialize(const nlohmann::json &data);
std::unordered_set<std::string> grants() const;
std::unordered_set<std::string> denies() const;
private:
std::unordered_set<std::string> grants_{};
std::unordered_set<std::string> denies_{};
};
bool operator==(const LabelPermissions &first, const LabelPermissions &second);
bool operator!=(const LabelPermissions &first, const LabelPermissions &second);
class Role final { class Role final {
public: public:
Role(const std::string &rolename); Role(const std::string &rolename);
Role(const std::string &rolename, const Permissions &permissions); Role(const std::string &rolename, const Permissions &permissions);
Role(const std::string &rolename, const Permissions &permissions, const LabelPermissions &labelPermissions);
const std::string &rolename() const; const std::string &rolename() const;
const Permissions &permissions() const; const Permissions &permissions() const;
Permissions &permissions(); Permissions &permissions();
LabelPermissions &labelPermissions();
nlohmann::json Serialize() const; nlohmann::json Serialize() const;
/// @throw AuthException if unable to deserialize. /// @throw AuthException if unable to deserialize.
@@ -146,7 +114,6 @@ class Role final {
private: private:
std::string rolename_; std::string rolename_;
Permissions permissions_; Permissions permissions_;
LabelPermissions labelPermissions_;
}; };
bool operator==(const Role &first, const Role &second); bool operator==(const Role &first, const Role &second);
@@ -158,9 +125,6 @@ class User final {
User(const std::string &username, const std::string &password_hash, const Permissions &permissions); User(const std::string &username, const std::string &password_hash, const Permissions &permissions);
User(const std::string &username, const std::string &password_hash, const Permissions &permissions,
const LabelPermissions &labelPermissions);
/// @throw AuthException if unable to verify the password. /// @throw AuthException if unable to verify the password.
bool CheckPassword(const std::string &password); bool CheckPassword(const std::string &password);
@@ -180,8 +144,6 @@ class User final {
const Role *role() const; const Role *role() const;
LabelPermissions &labelPermissions();
nlohmann::json Serialize() const; nlohmann::json Serialize() const;
/// @throw AuthException if unable to deserialize. /// @throw AuthException if unable to deserialize.
@@ -194,9 +156,7 @@ class User final {
std::string password_hash_; std::string password_hash_;
Permissions permissions_; Permissions permissions_;
std::optional<Role> role_; std::optional<Role> role_;
LabelPermissions labelPermissions_;
}; };
bool operator==(const User &first, const User &second); bool operator==(const User &first, const User &second);
} // namespace auth
} // namespace memgraph::auth

View File

@@ -1,4 +1,4 @@
// Copyright 2022 Memgraph Ltd. // Copyright 2021 Memgraph Ltd.
// //
// Licensed as a Memgraph Enterprise file under the Memgraph Enterprise // Licensed as a Memgraph Enterprise file under the Memgraph Enterprise
// License (the "License"); by using this file, you agree to be bound by the terms of the License, and you may not use // License (the "License"); by using this file, you agree to be bound by the terms of the License, and you may not use
@@ -153,7 +153,7 @@ int Target(void *arg) {
// process and something really bad could happen. // process and something really bad could happen.
// Get a pointer to the passed arguments. // Get a pointer to the passed arguments.
auto *ta = reinterpret_cast<memgraph::auth::TargetArguments *>(arg); auto *ta = reinterpret_cast<auth::TargetArguments *>(arg);
// Redirect `stdin` to `/dev/null`. // Redirect `stdin` to `/dev/null`.
int fd = open("/dev/null", O_RDONLY | O_CLOEXEC); int fd = open("/dev/null", O_RDONLY | O_CLOEXEC);
@@ -312,7 +312,8 @@ nlohmann::json GetData(int fd, int timeout_millisec) {
} // namespace } // namespace
namespace memgraph::auth { namespace auth {
Module::Module(const std::filesystem::path &module_executable_path) { Module::Module(const std::filesystem::path &module_executable_path) {
if (!module_executable_path.empty()) { if (!module_executable_path.empty()) {
module_executable_path_ = std::filesystem::absolute(module_executable_path); module_executable_path_ = std::filesystem::absolute(module_executable_path);
@@ -446,4 +447,4 @@ void Module::Shutdown() {
Module::~Module() { Shutdown(); } Module::~Module() { Shutdown(); }
} // namespace memgraph::auth } // namespace auth

View File

@@ -1,4 +1,4 @@
// Copyright 2022 Memgraph Ltd. // Copyright 2021 Memgraph Ltd.
// //
// Licensed as a Memgraph Enterprise file under the Memgraph Enterprise // Licensed as a Memgraph Enterprise file under the Memgraph Enterprise
// License (the "License"); by using this file, you agree to be bound by the terms of the License, and you may not use // License (the "License"); by using this file, you agree to be bound by the terms of the License, and you may not use
@@ -16,7 +16,8 @@
#include <json/json.hpp> #include <json/json.hpp>
namespace memgraph::auth { namespace auth {
struct TargetArguments { struct TargetArguments {
std::filesystem::path module_executable_path; std::filesystem::path module_executable_path;
int pipe_to_module{-1}; int pipe_to_module{-1};
@@ -69,4 +70,4 @@ class Module final {
int pipe_from_module_[2] = {-1, -1}; int pipe_from_module_[2] = {-1, -1};
}; };
} // namespace memgraph::auth } // namespace auth

View File

@@ -18,24 +18,19 @@ roles_config = config["roles"]
# Initialize LDAP server. # Initialize LDAP server.
tls = None tls = None
if server_config["encryption"] != "disabled": if server_config["encryption"] != "disabled":
cert_file = server_config["cert_file"] if server_config["cert_file"] else None cert_file = server_config["cert_file"] if server_config["cert_file"] \
else None
key_file = server_config["key_file"] if server_config["key_file"] else None key_file = server_config["key_file"] if server_config["key_file"] else None
ca_file = server_config["ca_file"] if server_config["ca_file"] else None ca_file = server_config["ca_file"] if server_config["ca_file"] else None
validate = ssl.CERT_REQUIRED if server_config["validate_cert"] else ssl.CERT_NONE validate = ssl.CERT_REQUIRED if server_config["validate_cert"] \
tls = ldap3.Tls( else ssl.CERT_NONE
local_private_key_file=key_file, tls = ldap3.Tls(local_private_key_file=key_file,
local_certificate_file=cert_file, local_certificate_file=cert_file,
ca_certs_file=ca_file, ca_certs_file=ca_file,
validate=validate, validate=validate)
)
use_ssl = server_config["encryption"] == "ssl" use_ssl = server_config["encryption"] == "ssl"
server = ldap3.Server( server = ldap3.Server(server_config["host"], port=server_config["port"],
server_config["host"], tls=tls, use_ssl=use_ssl, get_info=ldap3.ALL)
port=server_config["port"],
tls=tls,
use_ssl=use_ssl,
get_info=ldap3.ALL,
)
# Main authentication/authorization function. # Main authentication/authorization function.
@@ -45,12 +40,14 @@ def authenticate(username, password):
return {"authenticated": False, "role": ""} return {"authenticated": False, "role": ""}
# Create the DN of the user # Create the DN of the user
dn = users_config["prefix"] + ldap3.utils.dn.escape_rdn(username) + users_config["suffix"] dn = users_config["prefix"] + ldap3.utils.dn.escape_rdn(username) + \
users_config["suffix"]
# Bind to the server # Bind to the server
conn = ldap3.Connection(server, dn, password) conn = ldap3.Connection(server, dn, password)
if server_config["encryption"] == "starttls" and not conn.start_tls(): if server_config["encryption"] == "starttls" and not conn.start_tls():
print("ERROR: Couldn't issue STARTTLS to the LDAP server!", file=sys.stderr) print("ERROR: Couldn't issue STARTTLS to the LDAP server!",
file=sys.stderr)
return {"authenticated": False, "role": ""} return {"authenticated": False, "role": ""}
if not conn.bind(): if not conn.bind():
return {"authenticated": False, "role": ""} return {"authenticated": False, "role": ""}
@@ -59,32 +56,25 @@ def authenticate(username, password):
if roles_config["root_dn"] != "": if roles_config["root_dn"] != "":
# search for role # search for role
search_filter = "(&(objectclass={objclass})({attr}={value}))".format( search_filter = "(&(objectclass={objclass})({attr}={value}))".format(
objclass=roles_config["root_objectclass"], objclass=roles_config["root_objectclass"],
attr=roles_config["user_attribute"], attr=roles_config["user_attribute"],
value=ldap3.utils.conv.escape_filter_chars(dn), value=ldap3.utils.conv.escape_filter_chars(dn))
) succ = conn.search(roles_config["root_dn"], search_filter,
succ = conn.search( search_scope=ldap3.LEVEL,
roles_config["root_dn"], attributes=[roles_config["role_attribute"]])
search_filter,
search_scope=ldap3.LEVEL,
attributes=[roles_config["role_attribute"]],
)
if not succ or len(conn.entries) == 0: if not succ or len(conn.entries) == 0:
return {"authenticated": True, "role": ""} return {"authenticated": True, "role": ""}
if len(conn.entries) > 1: if len(conn.entries) > 1:
roles = list(map(lambda x: x[roles_config["role_attribute"]].value, conn.entries)) roles = list(map(lambda x: x[roles_config["role_attribute"]].value,
conn.entries))
# Because we don't know exactly which role the user should have # Because we don't know exactly which role the user should have
# we authorize the user with an empty role. # we authorize the user with an empty role.
print( print("WARNING: Found more than one role for "
"WARNING: Found more than one role for " "user '" + username + "':", "user '" + username + "':", ", ".join(roles) + "!",
", ".join(roles) + "!", file=sys.stderr)
file=sys.stderr,
)
return {"authenticated": True, "role": ""} return {"authenticated": True, "role": ""}
return { return {"authenticated": True,
"authenticated": True, "role": conn.entries[0][roles_config["role_attribute"]].value}
"role": conn.entries[0][roles_config["role_attribute"]].value,
}
else: else:
return {"authenticated": True, "role": ""} return {"authenticated": True, "role": ""}

View File

@@ -2,10 +2,6 @@ find_package(fmt REQUIRED)
find_package(gflags REQUIRED) find_package(gflags REQUIRED)
set(communication_src_files set(communication_src_files
websocket/auth.cpp
websocket/server.cpp
websocket/listener.cpp
websocket/session.cpp
bolt/v1/value.cpp bolt/v1/value.cpp
buffer.cpp buffer.cpp
client.cpp client.cpp
@@ -13,10 +9,8 @@ set(communication_src_files
helpers.cpp helpers.cpp
init.cpp) init.cpp)
find_package(Boost REQUIRED)
add_library(mg-communication STATIC ${communication_src_files}) add_library(mg-communication STATIC ${communication_src_files})
target_link_libraries(mg-communication Boost::headers Threads::Threads mg-utils mg-io mg-auth fmt::fmt gflags) target_link_libraries(mg-communication Threads::Threads mg-utils mg-io fmt::fmt gflags)
find_package(OpenSSL REQUIRED) find_package(OpenSSL REQUIRED)
target_link_libraries(mg-communication ${OPENSSL_LIBRARIES}) target_link_libraries(mg-communication ${OPENSSL_LIBRARIES})

View File

@@ -1,4 +1,4 @@
// Copyright 2022 Memgraph Ltd. // Copyright 2021 Memgraph Ltd.
// //
// Use of this software is governed by the Business Source License // Use of this software is governed by the Business Source License
// included in the file licenses/BSL.txt; by using this file, you agree to be bound by the terms of the Business Source // included in the file licenses/BSL.txt; by using this file, you agree to be bound by the terms of the Business Source
@@ -21,7 +21,7 @@
#include "utils/exceptions.hpp" #include "utils/exceptions.hpp"
#include "utils/logging.hpp" #include "utils/logging.hpp"
namespace memgraph::communication::bolt { namespace communication::bolt {
/// This exception is thrown whenever an error occurs during query execution /// This exception is thrown whenever an error occurs during query execution
/// that isn't fatal (eg. mistyped query or some transient error occurred). /// that isn't fatal (eg. mistyped query or some transient error occurred).
@@ -315,4 +315,4 @@ class Client final {
ChunkedEncoderBuffer<communication::ClientOutputStream> encoder_buffer_{output_stream_}; ChunkedEncoderBuffer<communication::ClientOutputStream> encoder_buffer_{output_stream_};
ClientEncoder<ChunkedEncoderBuffer<communication::ClientOutputStream>> encoder_{encoder_buffer_}; ClientEncoder<ChunkedEncoderBuffer<communication::ClientOutputStream>> encoder_{encoder_buffer_};
}; };
} // namespace memgraph::communication::bolt } // namespace communication::bolt

View File

@@ -1,4 +1,4 @@
// Copyright 2022 Memgraph Ltd. // Copyright 2021 Memgraph Ltd.
// //
// Use of this software is governed by the Business Source License // Use of this software is governed by the Business Source License
// included in the file licenses/BSL.txt; by using this file, you agree to be bound by the terms of the Business Source // included in the file licenses/BSL.txt; by using this file, you agree to be bound by the terms of the Business Source
@@ -13,10 +13,10 @@
#include <cstdint> #include <cstdint>
namespace memgraph::communication::bolt { namespace communication::bolt {
inline constexpr uint8_t kPreamble[4] = {0x60, 0x60, 0xB0, 0x17}; static constexpr uint8_t kPreamble[4] = {0x60, 0x60, 0xB0, 0x17};
inline constexpr uint8_t kProtocol[4] = {0x00, 0x00, 0x00, 0x01}; static constexpr uint8_t kProtocol[4] = {0x00, 0x00, 0x00, 0x01};
enum class Signature : uint8_t { enum class Signature : uint8_t {
Noop = 0x00, Noop = 0x00,
@@ -95,9 +95,9 @@ enum class Marker : uint8_t {
Struct16 = 0xDD, Struct16 = 0xDD,
}; };
inline constexpr uint8_t MarkerString = 0, MarkerList = 1, MarkerMap = 2; static constexpr uint8_t MarkerString = 0, MarkerList = 1, MarkerMap = 2;
inline constexpr Marker MarkerTiny[3] = {Marker::TinyString, Marker::TinyList, Marker::TinyMap}; static constexpr Marker MarkerTiny[3] = {Marker::TinyString, Marker::TinyList, Marker::TinyMap};
inline constexpr Marker Marker8[3] = {Marker::String8, Marker::List8, Marker::Map8}; static constexpr Marker Marker8[3] = {Marker::String8, Marker::List8, Marker::Map8};
inline constexpr Marker Marker16[3] = {Marker::String16, Marker::List16, Marker::Map16}; static constexpr Marker Marker16[3] = {Marker::String16, Marker::List16, Marker::Map16};
inline constexpr Marker Marker32[3] = {Marker::String32, Marker::List32, Marker::Map32}; static constexpr Marker Marker32[3] = {Marker::String32, Marker::List32, Marker::Map32};
} // namespace memgraph::communication::bolt } // namespace communication::bolt

View File

@@ -1,4 +1,4 @@
// Copyright 2022 Memgraph Ltd. // Copyright 2021 Memgraph Ltd.
// //
// Use of this software is governed by the Business Source License // Use of this software is governed by the Business Source License
// included in the file licenses/BSL.txt; by using this file, you agree to be bound by the terms of the Business Source // included in the file licenses/BSL.txt; by using this file, you agree to be bound by the terms of the Business Source
@@ -14,22 +14,22 @@
#include <cstddef> #include <cstddef>
#include <cstdint> #include <cstdint>
namespace memgraph::communication::bolt { namespace communication::bolt {
/** /**
* Sizes related to the chunk defined in Bolt protocol. * Sizes related to the chunk defined in Bolt protocol.
*/ */
inline constexpr size_t kChunkHeaderSize = 2; static constexpr size_t kChunkHeaderSize = 2;
inline constexpr size_t kChunkMaxDataSize = 65535; static constexpr size_t kChunkMaxDataSize = 65535;
inline constexpr size_t kChunkWholeSize = kChunkHeaderSize + kChunkMaxDataSize; static constexpr size_t kChunkWholeSize = kChunkHeaderSize + kChunkMaxDataSize;
/** /**
* Handshake size defined in the Bolt protocol. * Handshake size defined in the Bolt protocol.
*/ */
inline constexpr size_t kHandshakeSize = 20; static constexpr size_t kHandshakeSize = 20;
inline constexpr uint16_t kSupportedVersions[] = {0x0100, 0x0400, 0x0401, 0x0403}; static constexpr uint16_t kSupportedVersions[] = {0x0100, 0x0400, 0x0401, 0x0403};
inline constexpr int kPullAll = -1; static constexpr int kPullAll = -1;
inline constexpr int kPullLast = -1; static constexpr int kPullLast = -1;
} // namespace memgraph::communication::bolt } // namespace communication::bolt

View File

@@ -1,4 +1,4 @@
// Copyright 2022 Memgraph Ltd. // Copyright 2021 Memgraph Ltd.
// //
// Use of this software is governed by the Business Source License // Use of this software is governed by the Business Source License
// included in the file licenses/BSL.txt; by using this file, you agree to be bound by the terms of the Business Source // included in the file licenses/BSL.txt; by using this file, you agree to be bound by the terms of the Business Source
@@ -20,7 +20,7 @@
#include "communication/bolt/v1/constants.hpp" #include "communication/bolt/v1/constants.hpp"
namespace memgraph::communication::bolt { namespace communication::bolt {
/** /**
* This class is used as the return value of the GetChunk function of the * This class is used as the return value of the GetChunk function of the
@@ -136,4 +136,4 @@ class ChunkedDecoderBuffer {
std::vector<uint8_t> data_; std::vector<uint8_t> data_;
size_t pos_{0}; size_t pos_{0};
}; };
} // namespace memgraph::communication::bolt } // namespace communication::bolt

View File

@@ -1,4 +1,4 @@
// Copyright 2022 Memgraph Ltd. // Copyright 2021 Memgraph Ltd.
// //
// Use of this software is governed by the Business Source License // Use of this software is governed by the Business Source License
// included in the file licenses/BSL.txt; by using this file, you agree to be bound by the terms of the Business Source // included in the file licenses/BSL.txt; by using this file, you agree to be bound by the terms of the Business Source
@@ -22,7 +22,7 @@
#include "utils/logging.hpp" #include "utils/logging.hpp"
#include "utils/temporal.hpp" #include "utils/temporal.hpp"
namespace memgraph::communication::bolt { namespace communication::bolt {
/** /**
* Bolt Decoder. * Bolt Decoder.
@@ -591,4 +591,4 @@ class Decoder {
return true; return true;
} }
}; };
} // namespace memgraph::communication::bolt } // namespace communication::bolt

View File

@@ -1,4 +1,4 @@
// Copyright 2022 Memgraph Ltd. // Copyright 2021 Memgraph Ltd.
// //
// Use of this software is governed by the Business Source License // Use of this software is governed by the Business Source License
// included in the file licenses/BSL.txt; by using this file, you agree to be bound by the terms of the Business Source // included in the file licenses/BSL.txt; by using this file, you agree to be bound by the terms of the Business Source
@@ -22,7 +22,7 @@ static_assert(std::is_same_v<std::uint8_t, char> || std::is_same_v<std::uint8_t,
"communication::bolt::Encoder requires uint8_t to be " "communication::bolt::Encoder requires uint8_t to be "
"implemented as char or unsigned char."); "implemented as char or unsigned char.");
namespace memgraph::communication::bolt { namespace communication::bolt {
/** /**
* Bolt BaseEncoder. Has public interfaces for writing Bolt encoded data. * Bolt BaseEncoder. Has public interfaces for writing Bolt encoded data.
@@ -273,4 +273,4 @@ class BaseEncoder {
} }
}; };
} // namespace memgraph::communication::bolt } // namespace communication::bolt

View File

@@ -1,4 +1,4 @@
// Copyright 2022 Memgraph Ltd. // Copyright 2021 Memgraph Ltd.
// //
// Use of this software is governed by the Business Source License // Use of this software is governed by the Business Source License
// included in the file licenses/BSL.txt; by using this file, you agree to be bound by the terms of the Business Source // included in the file licenses/BSL.txt; by using this file, you agree to be bound by the terms of the Business Source
@@ -18,7 +18,7 @@
#include "communication/bolt/v1/constants.hpp" #include "communication/bolt/v1/constants.hpp"
namespace memgraph::communication::bolt { namespace communication::bolt {
/** /**
* @brief ChunkedEncoderBuffer * @brief ChunkedEncoderBuffer
@@ -123,4 +123,4 @@ class ChunkedEncoderBuffer {
// Amount of data in chunk array. // Amount of data in chunk array.
size_t have_{0}; size_t have_{0};
}; };
} // namespace memgraph::communication::bolt } // namespace communication::bolt

View File

@@ -1,4 +1,4 @@
// Copyright 2022 Memgraph Ltd. // Copyright 2021 Memgraph Ltd.
// //
// Use of this software is governed by the Business Source License // Use of this software is governed by the Business Source License
// included in the file licenses/BSL.txt; by using this file, you agree to be bound by the terms of the Business Source // included in the file licenses/BSL.txt; by using this file, you agree to be bound by the terms of the Business Source
@@ -14,7 +14,7 @@
#include "communication/bolt/v1/codes.hpp" #include "communication/bolt/v1/codes.hpp"
#include "communication/bolt/v1/encoder/base_encoder.hpp" #include "communication/bolt/v1/encoder/base_encoder.hpp"
namespace memgraph::communication::bolt { namespace communication::bolt {
/** /**
* Bolt Client Encoder. * Bolt Client Encoder.
@@ -169,4 +169,4 @@ class ClientEncoder : private BaseEncoder<Buffer> {
return buffer_.Flush(); return buffer_.Flush();
} }
}; };
} // namespace memgraph::communication::bolt } // namespace communication::bolt

View File

@@ -1,4 +1,4 @@
// Copyright 2022 Memgraph Ltd. // Copyright 2021 Memgraph Ltd.
// //
// Use of this software is governed by the Business Source License // Use of this software is governed by the Business Source License
// included in the file licenses/BSL.txt; by using this file, you agree to be bound by the terms of the Business Source // included in the file licenses/BSL.txt; by using this file, you agree to be bound by the terms of the Business Source
@@ -14,7 +14,7 @@
#include "communication/bolt/v1/codes.hpp" #include "communication/bolt/v1/codes.hpp"
#include "communication/bolt/v1/encoder/base_encoder.hpp" #include "communication/bolt/v1/encoder/base_encoder.hpp"
namespace memgraph::communication::bolt { namespace communication::bolt {
/** /**
* Bolt Encoder. * Bolt Encoder.
@@ -158,4 +158,4 @@ class Encoder : private BaseEncoder<Buffer> {
return buffer_.Flush(); return buffer_.Flush();
} }
}; };
} // namespace memgraph::communication::bolt } // namespace communication::bolt

View File

@@ -1,4 +1,4 @@
// Copyright 2022 Memgraph Ltd. // Copyright 2021 Memgraph Ltd.
// //
// Use of this software is governed by the Business Source License // Use of this software is governed by the Business Source License
// included in the file licenses/BSL.txt; by using this file, you agree to be bound by the terms of the Business Source // included in the file licenses/BSL.txt; by using this file, you agree to be bound by the terms of the Business Source
@@ -17,7 +17,7 @@
#include "utils/exceptions.hpp" #include "utils/exceptions.hpp"
namespace memgraph::communication::bolt { namespace communication::bolt {
/** /**
* Used to indicate something is wrong with the client but the transaction is * Used to indicate something is wrong with the client but the transaction is
@@ -83,4 +83,4 @@ class VerboseError : public utils::BasicException {
std::string code_; std::string code_;
}; };
} // namespace memgraph::communication::bolt } // namespace communication::bolt

View File

@@ -1,4 +1,4 @@
// Copyright 2022 Memgraph Ltd. // Copyright 2021 Memgraph Ltd.
// //
// Use of this software is governed by the Business Source License // Use of this software is governed by the Business Source License
// included in the file licenses/BSL.txt; by using this file, you agree to be bound by the terms of the Business Source // included in the file licenses/BSL.txt; by using this file, you agree to be bound by the terms of the Business Source
@@ -27,7 +27,7 @@
#include "utils/exceptions.hpp" #include "utils/exceptions.hpp"
#include "utils/logging.hpp" #include "utils/logging.hpp"
namespace memgraph::communication::bolt { namespace communication::bolt {
/** /**
* Bolt Session Exception * Bolt Session Exception
@@ -195,4 +195,4 @@ class Session {
} }
}; };
} // namespace memgraph::communication::bolt } // namespace communication::bolt

View File

@@ -1,4 +1,4 @@
// Copyright 2022 Memgraph Ltd. // Copyright 2021 Memgraph Ltd.
// //
// Use of this software is governed by the Business Source License // Use of this software is governed by the Business Source License
// included in the file licenses/BSL.txt; by using this file, you agree to be bound by the terms of the Business Source // included in the file licenses/BSL.txt; by using this file, you agree to be bound by the terms of the Business Source
@@ -13,7 +13,7 @@
#include <cstdint> #include <cstdint>
namespace memgraph::communication::bolt { namespace communication::bolt {
/** /**
* This class represents states in execution of the Bolt protocol. * This class represents states in execution of the Bolt protocol.
@@ -55,4 +55,4 @@ enum class State : uint8_t {
*/ */
Close Close
}; };
} // namespace memgraph::communication::bolt } // namespace communication::bolt

View File

@@ -1,4 +1,4 @@
// Copyright 2022 Memgraph Ltd. // Copyright 2021 Memgraph Ltd.
// //
// Use of this software is governed by the Business Source License // Use of this software is governed by the Business Source License
// included in the file licenses/BSL.txt; by using this file, you agree to be bound by the terms of the Business Source // included in the file licenses/BSL.txt; by using this file, you agree to be bound by the terms of the Business Source
@@ -20,7 +20,7 @@
#include "utils/likely.hpp" #include "utils/likely.hpp"
#include "utils/logging.hpp" #include "utils/logging.hpp"
namespace memgraph::communication::bolt { namespace communication::bolt {
/** /**
* Error state run function * Error state run function
@@ -95,4 +95,4 @@ State StateErrorRun(TSession &session, State state) {
return state; return state;
} }
} }
} // namespace memgraph::communication::bolt } // namespace communication::bolt

View File

@@ -1,4 +1,4 @@
// Copyright 2022 Memgraph Ltd. // Copyright 2021 Memgraph Ltd.
// //
// Use of this software is governed by the Business Source License // Use of this software is governed by the Business Source License
// included in the file licenses/BSL.txt; by using this file, you agree to be bound by the terms of the Business Source // included in the file licenses/BSL.txt; by using this file, you agree to be bound by the terms of the Business Source
@@ -26,7 +26,7 @@
#include "utils/logging.hpp" #include "utils/logging.hpp"
#include "utils/message.hpp" #include "utils/message.hpp"
namespace memgraph::communication::bolt { namespace communication::bolt {
template <typename TSession> template <typename TSession>
State RunHandlerV1(Signature signature, TSession &session, State state, Marker marker) { State RunHandlerV1(Signature signature, TSession &session, State state, Marker marker) {
@@ -118,4 +118,4 @@ State StateExecutingRun(TSession &session, State state) {
return State::Close; return State::Close;
} }
} }
} // namespace memgraph::communication::bolt } // namespace communication::bolt

View File

@@ -1,4 +1,4 @@
// Copyright 2022 Memgraph Ltd. // Copyright 2021 Memgraph Ltd.
// //
// Use of this software is governed by the Business Source License // Use of this software is governed by the Business Source License
// included in the file licenses/BSL.txt; by using this file, you agree to be bound by the terms of the Business Source // included in the file licenses/BSL.txt; by using this file, you agree to be bound by the terms of the Business Source
@@ -24,7 +24,7 @@
#include "utils/logging.hpp" #include "utils/logging.hpp"
#include "utils/message.hpp" #include "utils/message.hpp"
namespace memgraph::communication::bolt { namespace communication::bolt {
// TODO: Revise these error messages // TODO: Revise these error messages
inline std::pair<std::string, std::string> ExceptionToErrorMessage(const std::exception &e) { inline std::pair<std::string, std::string> ExceptionToErrorMessage(const std::exception &e) {
if (const auto *verbose = dynamic_cast<const VerboseError *>(&e)) { if (const auto *verbose = dynamic_cast<const VerboseError *>(&e)) {
@@ -415,4 +415,4 @@ State HandleRoute(TSession &session) {
} }
return State::Error; return State::Error;
} }
} // namespace memgraph::communication::bolt } // namespace communication::bolt

View File

@@ -1,4 +1,4 @@
// Copyright 2022 Memgraph Ltd. // Copyright 2021 Memgraph Ltd.
// //
// Use of this software is governed by the Business Source License // Use of this software is governed by the Business Source License
// included in the file licenses/BSL.txt; by using this file, you agree to be bound by the terms of the Business Source // included in the file licenses/BSL.txt; by using this file, you agree to be bound by the terms of the Business Source
@@ -22,7 +22,7 @@
#include "utils/likely.hpp" #include "utils/likely.hpp"
#include "utils/logging.hpp" #include "utils/logging.hpp"
namespace memgraph::communication::bolt { namespace communication::bolt {
inline bool CopyProtocolInformationIfSupported(uint16_t version, uint8_t *protocol) { inline bool CopyProtocolInformationIfSupported(uint16_t version, uint8_t *protocol) {
const auto *supported_version = std::find(std::begin(kSupportedVersions), std::end(kSupportedVersions), version); const auto *supported_version = std::find(std::begin(kSupportedVersions), std::end(kSupportedVersions), version);
@@ -110,4 +110,4 @@ State StateHandshakeRun(TSession &session) {
return State::Init; return State::Init;
} }
} // namespace memgraph::communication::bolt } // namespace communication::bolt

View File

@@ -1,4 +1,4 @@
// Copyright 2022 Memgraph Ltd. // Copyright 2021 Memgraph Ltd.
// //
// Use of this software is governed by the Business Source License // Use of this software is governed by the Business Source License
// included in the file licenses/BSL.txt; by using this file, you agree to be bound by the terms of the Business Source // included in the file licenses/BSL.txt; by using this file, you agree to be bound by the terms of the Business Source
@@ -21,7 +21,7 @@
#include "utils/likely.hpp" #include "utils/likely.hpp"
#include "utils/logging.hpp" #include "utils/logging.hpp"
namespace memgraph::communication::bolt { namespace communication::bolt {
namespace details { namespace details {
template <typename TSession> template <typename TSession>
@@ -212,4 +212,4 @@ State StateInitRun(TSession &session) {
spdlog::trace("Unsupported bolt version:{}.{})!", session.version_.major, session.version_.minor); spdlog::trace("Unsupported bolt version:{}.{})!", session.version_.major, session.version_.minor);
return State::Close; return State::Close;
} }
} // namespace memgraph::communication::bolt } // namespace communication::bolt

View File

@@ -1,4 +1,4 @@
// Copyright 2022 Memgraph Ltd. // Copyright 2021 Memgraph Ltd.
// //
// Use of this software is governed by the Business Source License // Use of this software is governed by the Business Source License
// included in the file licenses/BSL.txt; by using this file, you agree to be bound by the terms of the Business Source // included in the file licenses/BSL.txt; by using this file, you agree to be bound by the terms of the Business Source
@@ -14,7 +14,7 @@
#include "utils/algorithm.hpp" #include "utils/algorithm.hpp"
#include "utils/string.hpp" #include "utils/string.hpp"
namespace memgraph::communication::bolt { namespace communication::bolt {
#define DEF_GETTER_BY_VAL(type, value_type, field) \ #define DEF_GETTER_BY_VAL(type, value_type, field) \
value_type &Value::Value##type() { \ value_type &Value::Value##type() { \
@@ -461,4 +461,4 @@ std::ostream &operator<<(std::ostream &os, const Value::Type type) {
return os << "duration"; return os << "duration";
} }
} }
} // namespace memgraph::communication::bolt } // namespace communication::bolt

View File

@@ -1,4 +1,4 @@
// Copyright 2022 Memgraph Ltd. // Copyright 2021 Memgraph Ltd.
// //
// Use of this software is governed by the Business Source License // Use of this software is governed by the Business Source License
// included in the file licenses/BSL.txt; by using this file, you agree to be bound by the terms of the Business Source // included in the file licenses/BSL.txt; by using this file, you agree to be bound by the terms of the Business Source
@@ -20,7 +20,7 @@
#include "utils/exceptions.hpp" #include "utils/exceptions.hpp"
#include "utils/temporal.hpp" #include "utils/temporal.hpp"
namespace memgraph::communication::bolt { namespace communication::bolt {
/** Forward declaration of Value class. */ /** Forward declaration of Value class. */
class Value; class Value;
@@ -282,4 +282,4 @@ std::ostream &operator<<(std::ostream &os, const UnboundedEdge &edge);
std::ostream &operator<<(std::ostream &os, const Path &path); std::ostream &operator<<(std::ostream &os, const Path &path);
std::ostream &operator<<(std::ostream &os, const Value &value); std::ostream &operator<<(std::ostream &os, const Value &value);
std::ostream &operator<<(std::ostream &os, const Value::Type type); std::ostream &operator<<(std::ostream &os, const Value::Type type);
} // namespace memgraph::communication::bolt } // namespace communication::bolt

View File

@@ -1,4 +1,4 @@
// Copyright 2022 Memgraph Ltd. // Copyright 2021 Memgraph Ltd.
// //
// Use of this software is governed by the Business Source License // Use of this software is governed by the Business Source License
// included in the file licenses/BSL.txt; by using this file, you agree to be bound by the terms of the Business Source // included in the file licenses/BSL.txt; by using this file, you agree to be bound by the terms of the Business Source
@@ -13,7 +13,7 @@
#include "utils/logging.hpp" #include "utils/logging.hpp"
namespace memgraph::communication { namespace communication {
Buffer::Buffer() : data_(kBufferInitialSize, 0), read_end_(this), write_end_(this) {} Buffer::Buffer() : data_(kBufferInitialSize, 0), read_end_(this), write_end_(this) {}
@@ -77,4 +77,4 @@ void Buffer::Resize(size_t len) {
void Buffer::Clear() { have_ = 0; } void Buffer::Clear() { have_ = 0; }
} // namespace memgraph::communication } // namespace communication

View File

@@ -1,4 +1,4 @@
// Copyright 2022 Memgraph Ltd. // Copyright 2021 Memgraph Ltd.
// //
// Use of this software is governed by the Business Source License // Use of this software is governed by the Business Source License
// included in the file licenses/BSL.txt; by using this file, you agree to be bound by the terms of the Business Source // included in the file licenses/BSL.txt; by using this file, you agree to be bound by the terms of the Business Source
@@ -15,7 +15,7 @@
#include "io/network/stream_buffer.hpp" #include "io/network/stream_buffer.hpp"
namespace memgraph::communication { namespace communication {
/** /**
* @brief Buffer * @brief Buffer
@@ -171,4 +171,4 @@ class Buffer final {
ReadEnd read_end_; ReadEnd read_end_;
WriteEnd write_end_; WriteEnd write_end_;
}; };
} // namespace memgraph::communication } // namespace communication

View File

@@ -1,4 +1,4 @@
// Copyright 2022 Memgraph Ltd. // Copyright 2021 Memgraph Ltd.
// //
// Use of this software is governed by the Business Source License // Use of this software is governed by the Business Source License
// included in the file licenses/BSL.txt; by using this file, you agree to be bound by the terms of the Business Source // included in the file licenses/BSL.txt; by using this file, you agree to be bound by the terms of the Business Source
@@ -14,7 +14,7 @@
#include "communication/helpers.hpp" #include "communication/helpers.hpp"
#include "utils/logging.hpp" #include "utils/logging.hpp"
namespace memgraph::communication { namespace communication {
Client::Client(ClientContext *context) : context_(context) {} Client::Client(ClientContext *context) : context_(context) {}
@@ -239,4 +239,4 @@ bool ClientOutputStream::Write(const uint8_t *data, size_t len, bool have_more)
} }
bool ClientOutputStream::Write(const std::string &str, bool have_more) { return client_.Write(str, have_more); } bool ClientOutputStream::Write(const std::string &str, bool have_more) { return client_.Write(str, have_more); }
} // namespace memgraph::communication } // namespace communication

View File

@@ -1,4 +1,4 @@
// Copyright 2022 Memgraph Ltd. // Copyright 2021 Memgraph Ltd.
// //
// Use of this software is governed by the Business Source License // Use of this software is governed by the Business Source License
// included in the file licenses/BSL.txt; by using this file, you agree to be bound by the terms of the Business Source // included in the file licenses/BSL.txt; by using this file, you agree to be bound by the terms of the Business Source
@@ -21,14 +21,14 @@
#include "io/network/endpoint.hpp" #include "io/network/endpoint.hpp"
#include "io/network/socket.hpp" #include "io/network/socket.hpp"
namespace memgraph::communication { namespace communication {
/** /**
* This class implements a generic network Client. * This class implements a generic network Client.
* It uses blocking sockets and provides an API that can be used to receive/send * It uses blocking sockets and provides an API that can be used to receive/send
* data over the network connection. * data over the network connection.
* *
* NOTE: If you use this client you **must** create `memgraph::communication::SSLInit` * NOTE: If you use this client you **must** create `communication::SSLInit`
* from the `main` function before using the client! * from the `main` function before using the client!
*/ */
class Client final { class Client final {
@@ -167,4 +167,4 @@ class ClientOutputStream final {
Client &client_; Client &client_;
}; };
} // namespace memgraph::communication } // namespace communication

View File

@@ -1,4 +1,4 @@
// Copyright 2022 Memgraph Ltd. // Copyright 2021 Memgraph Ltd.
// //
// Use of this software is governed by the Business Source License // Use of this software is governed by the Business Source License
// included in the file licenses/BSL.txt; by using this file, you agree to be bound by the terms of the Business Source // included in the file licenses/BSL.txt; by using this file, you agree to be bound by the terms of the Business Source
@@ -10,13 +10,10 @@
// licenses/APL.txt. // licenses/APL.txt.
#include "communication/context.hpp" #include "communication/context.hpp"
#include <boost/asio/ssl/context.hpp>
#include <boost/asio/ssl/verify_mode.hpp>
#include <boost/system/detail/error_code.hpp>
#include "utils/logging.hpp" #include "utils/logging.hpp"
namespace memgraph::communication { namespace communication {
ClientContext::ClientContext(bool use_ssl) : use_ssl_(use_ssl), ctx_(nullptr) { ClientContext::ClientContext(bool use_ssl) : use_ssl_(use_ssl), ctx_(nullptr) {
if (use_ssl_) { if (use_ssl_) {
@@ -76,66 +73,80 @@ SSL_CTX *ClientContext::context() { return ctx_; }
bool ClientContext::use_ssl() { return use_ssl_; } bool ClientContext::use_ssl() { return use_ssl_; }
ServerContext::ServerContext() : use_ssl_(false), ctx_(nullptr) {}
ServerContext::ServerContext(const std::string &key_file, const std::string &cert_file, const std::string &ca_file, ServerContext::ServerContext(const std::string &key_file, const std::string &cert_file, const std::string &ca_file,
bool verify_peer) { bool verify_peer)
namespace ssl = boost::asio::ssl; : use_ssl_(true),
ctx_.emplace(ssl::context::tls_server); #if OPENSSL_VERSION_NUMBER < 0x10100000L
// NOLINTNEXTLINE(hicpp-signed-bitwise) ctx_(SSL_CTX_new(SSLv23_server_method()))
ctx_->set_options(ssl::context::default_workarounds | ssl::context::no_sslv2 | ssl::context::no_sslv3 | #else
ssl::context::single_dh_use); ctx_(SSL_CTX_new(TLS_server_method()))
ctx_->set_default_verify_paths(); #endif
// TODO: add support for encrypted private keys {
// TODO: add certificate revocation list (CRL) // TODO (mferencevic): add support for encrypted private keys
boost::system::error_code ec; // TODO (mferencevic): add certificate revocation list (CRL)
ctx_->use_certificate_chain_file(cert_file, ec); MG_ASSERT(SSL_CTX_use_certificate_file(ctx_, cert_file.c_str(), SSL_FILETYPE_PEM) == 1,
MG_ASSERT(!ec, "Couldn't load server certificate from file: {}", cert_file); "Couldn't load server certificate from file: {}", cert_file);
ctx_->use_private_key_file(key_file, ssl::context::pem, ec); MG_ASSERT(SSL_CTX_use_PrivateKey_file(ctx_, key_file.c_str(), SSL_FILETYPE_PEM) == 1,
MG_ASSERT(!ec, "Couldn't load server private key from file: {}", key_file); "Couldn't load server private key from file: {}", key_file);
ctx_->set_options(SSL_OP_NO_SSLv3, ec); // Disable legacy SSL support. Other options can be seen here:
MG_ASSERT(!ec, "Setting options to SSL context failed!"); // https://www.openssl.org/docs/man1.0.2/ssl/SSL_CTX_set_options.html
SSL_CTX_set_options(ctx_, SSL_OP_NO_SSLv3);
if (!ca_file.empty()) { if (ca_file != "") {
// Load the certificate authority file. // Load the certificate authority file.
boost::system::error_code ec; MG_ASSERT(SSL_CTX_load_verify_locations(ctx_, ca_file.c_str(), nullptr) == 1,
ctx_->load_verify_file(ca_file, ec); "Couldn't load certificate authority from file: {}", ca_file);
MG_ASSERT(!ec, "Couldn't load certificate authority from file: {}", ca_file);
if (verify_peer) { if (verify_peer) {
// Add the CA to list of accepted CAs that is sent to the client.
STACK_OF(X509_NAME) *ca_names = SSL_load_client_CA_file(ca_file.c_str());
MG_ASSERT(ca_names != nullptr, "Couldn't load certificate authority from file: {}", ca_file);
// `ca_names` doesn' need to be free'd because we pass it to
// `SSL_CTX_set_client_CA_list`:
// https://mta.openssl.org/pipermail/openssl-users/2015-May/001363.html
SSL_CTX_set_client_CA_list(ctx_, ca_names);
// Enable verification of the client certificate. // Enable verification of the client certificate.
// NOLINTNEXTLINE(hicpp-signed-bitwise) SSL_CTX_set_verify(ctx_, SSL_VERIFY_PEER | SSL_VERIFY_FAIL_IF_NO_PEER_CERT, nullptr);
ctx_->set_verify_mode(ssl::verify_peer | ssl::verify_fail_if_no_peer_cert, ec);
MG_ASSERT(!ec, "Setting SSL verification mode failed!");
} }
} }
} }
ServerContext::ServerContext(ServerContext &&other) noexcept { std::swap(ctx_, other.ctx_); } ServerContext::ServerContext(ServerContext &&other) noexcept : use_ssl_(other.use_ssl_), ctx_(other.ctx_) {
other.use_ssl_ = false;
other.ctx_ = nullptr;
}
ServerContext &ServerContext::operator=(ServerContext &&other) noexcept { ServerContext &ServerContext::operator=(ServerContext &&other) noexcept {
if (this == &other) return *this; if (this == &other) return *this;
// destroy my objects
if (use_ssl_) {
SSL_CTX_free(ctx_);
}
// move other objects to self // move other objects to self
ctx_ = std::move(other.ctx_); use_ssl_ = other.use_ssl_;
ctx_ = other.ctx_;
// reset other objects // reset other objects
other.ctx_.reset(); other.use_ssl_ = false;
other.ctx_ = nullptr;
return *this; return *this;
} }
ServerContext::~ServerContext() {} ServerContext::~ServerContext() {
if (use_ssl_) {
SSL_CTX *ServerContext::context() { SSL_CTX_free(ctx_);
MG_ASSERT(ctx_); }
return ctx_->native_handle();
} }
boost::asio::ssl::context &ServerContext::context_clone() { SSL_CTX *ServerContext::context() { return ctx_; }
MG_ASSERT(ctx_);
return *ctx_;
}
bool ServerContext::use_ssl() const { return ctx_.has_value(); } bool ServerContext::use_ssl() { return use_ssl_; }
} // namespace memgraph::communication } // namespace communication

View File

@@ -1,4 +1,4 @@
// Copyright 2022 Memgraph Ltd. // Copyright 2021 Memgraph Ltd.
// //
// Use of this software is governed by the Business Source License // Use of this software is governed by the Business Source License
// included in the file licenses/BSL.txt; by using this file, you agree to be bound by the terms of the Business Source // included in the file licenses/BSL.txt; by using this file, you agree to be bound by the terms of the Business Source
@@ -11,13 +11,11 @@
#pragma once #pragma once
#include <optional>
#include <string> #include <string>
#include <openssl/ssl.h> #include <openssl/ssl.h>
#include <boost/asio/ssl/context.hpp>
namespace memgraph::communication { namespace communication {
/** /**
* This class represents a context that should be used with network clients. One * This class represents a context that should be used with network clients. One
@@ -71,7 +69,11 @@ class ClientContext final {
*/ */
class ServerContext final { class ServerContext final {
public: public:
ServerContext() = default; /**
* This constructor constructs a ServerContext that doesn't use SSL.
*/
ServerContext();
/** /**
* This constructor constructs a ServerContext that uses SSL. The parameters * This constructor constructs a ServerContext that uses SSL. The parameters
* `key_file` and `cert_file` can't be "" because when setting up a server it * `key_file` and `cert_file` can't be "" because when setting up a server it
@@ -93,15 +95,16 @@ class ServerContext final {
ServerContext(ServerContext &&other) noexcept; ServerContext(ServerContext &&other) noexcept;
ServerContext &operator=(ServerContext &&other) noexcept; ServerContext &operator=(ServerContext &&other) noexcept;
// Destructor that handles ownership of the SSL object.
~ServerContext(); ~ServerContext();
SSL_CTX *context(); SSL_CTX *context();
boost::asio::ssl::context &context_clone();
bool use_ssl() const; bool use_ssl();
private: private:
std::optional<boost::asio::ssl::context> ctx_; bool use_ssl_;
SSL_CTX *ctx_;
}; };
} // namespace memgraph::communication } // namespace communication

View File

@@ -1,4 +1,4 @@
// Copyright 2022 Memgraph Ltd. // Copyright 2021 Memgraph Ltd.
// //
// Use of this software is governed by the Business Source License // Use of this software is governed by the Business Source License
// included in the file licenses/BSL.txt; by using this file, you agree to be bound by the terms of the Business Source // included in the file licenses/BSL.txt; by using this file, you agree to be bound by the terms of the Business Source
@@ -13,7 +13,7 @@
#include "utils/exceptions.hpp" #include "utils/exceptions.hpp"
namespace memgraph::communication { namespace communication {
/** /**
* This exception is thrown to indicate to the communication stack that the * This exception is thrown to indicate to the communication stack that the
@@ -22,4 +22,4 @@ namespace memgraph::communication {
class SessionClosedException : public utils::BasicException { class SessionClosedException : public utils::BasicException {
using utils::BasicException::BasicException; using utils::BasicException::BasicException;
}; };
} // namespace memgraph::communication } // namespace communication

View File

@@ -1,4 +1,4 @@
// Copyright 2022 Memgraph Ltd. // Copyright 2021 Memgraph Ltd.
// //
// Use of this software is governed by the Business Source License // Use of this software is governed by the Business Source License
// included in the file licenses/BSL.txt; by using this file, you agree to be bound by the terms of the Business Source // included in the file licenses/BSL.txt; by using this file, you agree to be bound by the terms of the Business Source
@@ -13,7 +13,7 @@
#include "communication/helpers.hpp" #include "communication/helpers.hpp"
namespace memgraph::communication { namespace communication {
const std::string SslGetLastError() { const std::string SslGetLastError() {
char buff[2048]; char buff[2048];
@@ -21,4 +21,4 @@ const std::string SslGetLastError() {
ERR_error_string_n(err, buff, sizeof(buff)); ERR_error_string_n(err, buff, sizeof(buff));
return std::string(buff); return std::string(buff);
} }
} // namespace memgraph::communication } // namespace communication

View File

@@ -1,4 +1,4 @@
// Copyright 2022 Memgraph Ltd. // Copyright 2021 Memgraph Ltd.
// //
// Use of this software is governed by the Business Source License // Use of this software is governed by the Business Source License
// included in the file licenses/BSL.txt; by using this file, you agree to be bound by the terms of the Business Source // included in the file licenses/BSL.txt; by using this file, you agree to be bound by the terms of the Business Source
@@ -13,11 +13,11 @@
#include <string> #include <string>
namespace memgraph::communication { namespace communication {
/** /**
* This function reads and returns a string describing the last OpenSSL error. * This function reads and returns a string describing the last OpenSSL error.
*/ */
const std::string SslGetLastError(); const std::string SslGetLastError();
} // namespace memgraph::communication } // namespace communication

View File

@@ -1,4 +1,4 @@
// Copyright 2022 Memgraph Ltd. // Copyright 2021 Memgraph Ltd.
// //
// Use of this software is governed by the Business Source License // Use of this software is governed by the Business Source License
// included in the file licenses/BSL.txt; by using this file, you agree to be bound by the terms of the Business Source // included in the file licenses/BSL.txt; by using this file, you agree to be bound by the terms of the Business Source
@@ -20,7 +20,7 @@
#include "utils/signals.hpp" #include "utils/signals.hpp"
#include "utils/spin_lock.hpp" #include "utils/spin_lock.hpp"
namespace memgraph::communication { namespace communication {
namespace { namespace {
// OpenSSL before 1.1 did not have a out-of-the-box multithreading support // OpenSSL before 1.1 did not have a out-of-the-box multithreading support
@@ -72,4 +72,4 @@ SSLInit::SSLInit() {
} }
SSLInit::~SSLInit() { Cleanup(); } SSLInit::~SSLInit() { Cleanup(); }
} // namespace memgraph::communication } // namespace communication

View File

@@ -1,4 +1,4 @@
// Copyright 2022 Memgraph Ltd. // Copyright 2021 Memgraph Ltd.
// //
// Use of this software is governed by the Business Source License // Use of this software is governed by the Business Source License
// included in the file licenses/BSL.txt; by using this file, you agree to be bound by the terms of the Business Source // included in the file licenses/BSL.txt; by using this file, you agree to be bound by the terms of the Business Source
@@ -11,7 +11,7 @@
#pragma once #pragma once
namespace memgraph::communication { namespace communication {
/** /**
* Create this object in each `main` file that uses the Communication stack. It * Create this object in each `main` file that uses the Communication stack. It
@@ -36,4 +36,4 @@ struct SSLInit {
~SSLInit(); ~SSLInit();
}; };
} // namespace memgraph::communication } // namespace communication

View File

@@ -1,4 +1,4 @@
// Copyright 2022 Memgraph Ltd. // Copyright 2021 Memgraph Ltd.
// //
// Use of this software is governed by the Business Source License // Use of this software is governed by the Business Source License
// included in the file licenses/BSL.txt; by using this file, you agree to be bound by the terms of the Business Source // included in the file licenses/BSL.txt; by using this file, you agree to be bound by the terms of the Business Source
@@ -28,7 +28,7 @@
#include "utils/spin_lock.hpp" #include "utils/spin_lock.hpp"
#include "utils/thread.hpp" #include "utils/thread.hpp"
namespace memgraph::communication { namespace communication {
/** /**
* This class listens to events on an epoll object and processes them. * This class listens to events on an epoll object and processes them.
@@ -273,4 +273,4 @@ class Listener final {
const std::string service_name_; const std::string service_name_;
const size_t workers_count_; const size_t workers_count_;
}; };
} // namespace memgraph::communication } // namespace communication

View File

@@ -1,4 +1,4 @@
// Copyright 2022 Memgraph Ltd. // Copyright 2021 Memgraph Ltd.
// //
// Use of this software is governed by the Business Source License // Use of this software is governed by the Business Source License
// included in the file licenses/BSL.txt; by using this file, you agree to be bound by the terms of the Business Source // included in the file licenses/BSL.txt; by using this file, you agree to be bound by the terms of the Business Source
@@ -29,7 +29,7 @@
*/ */
class ResultStreamFaker { class ResultStreamFaker {
public: public:
explicit ResultStreamFaker(memgraph::storage::Storage *store) : store_(store) {} explicit ResultStreamFaker(storage::Storage *store) : store_(store) {}
ResultStreamFaker(const ResultStreamFaker &) = delete; ResultStreamFaker(const ResultStreamFaker &) = delete;
ResultStreamFaker &operator=(const ResultStreamFaker &) = delete; ResultStreamFaker &operator=(const ResultStreamFaker &) = delete;
@@ -38,25 +38,25 @@ class ResultStreamFaker {
void Header(const std::vector<std::string> &fields) { header_ = fields; } void Header(const std::vector<std::string> &fields) { header_ = fields; }
void Result(const std::vector<memgraph::communication::bolt::Value> &values) { results_.push_back(values); } void Result(const std::vector<communication::bolt::Value> &values) { results_.push_back(values); }
void Result(const std::vector<memgraph::query::TypedValue> &values) { void Result(const std::vector<query::TypedValue> &values) {
std::vector<memgraph::communication::bolt::Value> bvalues; std::vector<communication::bolt::Value> bvalues;
bvalues.reserve(values.size()); bvalues.reserve(values.size());
for (const auto &value : values) { for (const auto &value : values) {
auto maybe_value = memgraph::glue::ToBoltValue(value, *store_, memgraph::storage::View::NEW); auto maybe_value = glue::ToBoltValue(value, *store_, storage::View::NEW);
MG_ASSERT(maybe_value.HasValue()); MG_ASSERT(maybe_value.HasValue());
bvalues.push_back(std::move(*maybe_value)); bvalues.push_back(std::move(*maybe_value));
} }
results_.push_back(std::move(bvalues)); results_.push_back(std::move(bvalues));
} }
void Summary(const std::map<std::string, memgraph::communication::bolt::Value> &summary) { summary_ = summary; } void Summary(const std::map<std::string, communication::bolt::Value> &summary) { summary_ = summary; }
void Summary(const std::map<std::string, memgraph::query::TypedValue> &summary) { void Summary(const std::map<std::string, query::TypedValue> &summary) {
std::map<std::string, memgraph::communication::bolt::Value> bsummary; std::map<std::string, communication::bolt::Value> bsummary;
for (const auto &item : summary) { for (const auto &item : summary) {
auto maybe_value = memgraph::glue::ToBoltValue(item.second, *store_, memgraph::storage::View::NEW); auto maybe_value = glue::ToBoltValue(item.second, *store_, storage::View::NEW);
MG_ASSERT(maybe_value.HasValue()); MG_ASSERT(maybe_value.HasValue());
bsummary.insert({item.first, std::move(*maybe_value)}); bsummary.insert({item.first, std::move(*maybe_value)});
} }
@@ -119,17 +119,17 @@ class ResultStreamFaker {
// output the summary // output the summary
os << "Query summary: {"; os << "Query summary: {";
memgraph::utils::PrintIterable(os, results.GetSummary(), ", ", utils::PrintIterable(os, results.GetSummary(), ", ",
[&](auto &stream, const auto &kv) { stream << kv.first << ": " << kv.second; }); [&](auto &stream, const auto &kv) { stream << kv.first << ": " << kv.second; });
os << "}" << std::endl; os << "}" << std::endl;
return os; return os;
} }
private: private:
memgraph::storage::Storage *store_; storage::Storage *store_;
// the data that the record stream can accept // the data that the record stream can accept
std::vector<std::string> header_; std::vector<std::string> header_;
std::vector<std::vector<memgraph::communication::bolt::Value>> results_; std::vector<std::vector<communication::bolt::Value>> results_;
std::map<std::string, memgraph::communication::bolt::Value> summary_; std::map<std::string, communication::bolt::Value> summary_;
}; };

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