Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 2 additions & 5 deletions .github/workflows/check_bazel_tests.yml
Original file line number Diff line number Diff line change
Expand Up @@ -9,9 +9,6 @@ on:
env:
USE_BAZEL_VERSION: 8.3.1
BAZEL_PACKAGE_VERSION: 8.3.1
JAVA_PREFIX: /usr/lib/jvm/java-17-openjdk-amd64
PYTHON3_PREFIX: /usr
PYTHON3_VERSION: python3
PROTOBUF_BIN: protoc
PROTOBUF_LIBRARY_PREFIX: /usr/lib/x86_64-linux-gnu
PROTOBUF_INCLUDE_PREFIX: /usr/include
Expand All @@ -28,7 +25,7 @@ jobs:
- name: Install system dependencies
run: |
sudo apt-get update
sudo apt-get install -y curl libprotobuf-dev libzmq3-dev openjdk-17-jdk protobuf-compiler python3-dev python3-numpy valgrind
sudo apt-get install -y curl libprotobuf-dev libzmq3-dev protobuf-compiler valgrind
- name: Install bazel
run: |
BAZEL_PACKAGE_FILE="bazel_$BAZEL_PACKAGE_VERSION-linux-x86_64.deb"
Expand Down Expand Up @@ -70,7 +67,7 @@ jobs:
- name: Install system dependencies
run: |
sudo apt-get update
sudo apt-get install -y curl libprotobuf-dev libzmq3-dev openjdk-17-jdk protobuf-compiler python3-dev python3-numpy valgrind
sudo apt-get install -y curl libprotobuf-dev libzmq3-dev protobuf-compiler valgrind
- name: Install bazel
run: |
BAZEL_PACKAGE_FILE="bazel_$BAZEL_PACKAGE_VERSION-linux-x86_64.deb"
Expand Down
3 changes: 0 additions & 3 deletions udf-runner-cpp/v1/.bazelrc
Original file line number Diff line number Diff line change
@@ -1,8 +1,6 @@
build --lockfile_mode=off --copt='-std=c++17' --force_pic --action_env=PROTOBUF_BIN --action_env=PROTOBUF_LIBRARY_PREFIX --action_env=PROTOBUF_INCLUDE_PREFIX
# TODO add environment variables for R libraries
build:benchmark --define benchmark=true
build:java --define java=true --action_env=JAVA_PREFIX
build:python --define python=true --action_env=NUMPY_PREFIX --action_env=PYTHON3_SYSPATH --action_env=PYTHON3_PREFIX --action_env=PYTHON3_VERSION
build:fast-binary --define binary_type=fast_binary //:udf_runner_cpp_v1_gen
build:slow-wrapper --define binary_type=slow_wrapper //:udf_runner_cpp_v1_gen
build:static-binary //:udf_runner_cpp_v1_static_gen
Expand All @@ -26,5 +24,4 @@ build:valgrind -c dbg
build:valgrind --copt -g
build:valgrind --strip=never
build:valgrind --copt -DVALGRIND_ACTIVE
build:fix_conda_ar_tool --features=-archive_param_file
build:plugin_client --define plugin_client=true
1 change: 1 addition & 0 deletions udf-runner-cpp/v1/.gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ bazel-genfiles
bazel-out
bazel-src
bazel-testlogs
bazel-v1
bazel-exaudfclient
graph.in
graph.png
Expand Down
17 changes: 4 additions & 13 deletions udf-runner-cpp/v1/BUILD
Original file line number Diff line number Diff line change
Expand Up @@ -6,19 +6,11 @@ load("//:variables.bzl", "VM_ENABLED_DEFINES")
VM_ENABLED_DEPS=select({
"@exaudfclient_base//:benchmark": ["@exaudfclient_base//benchmark_container:benchmark_container"],
"//conditions:default": []
}) + select({
"@exaudfclient_base//:java": ["@exaudfclient_base//javacontainer:javacontainer"],
"//conditions:default": []
}) + select({
"@exaudfclient_base//:bash": ["@exaudfclient_base//streaming_container:streamingcontainer"],
"//conditions:default": []
})

VM_PYTHON3_DEPS=select({
"@exaudfclient_base//:python": ["@exaudfclient_base//python/python3:pythoncontainer"],
"//conditions:default": []
})


genrule(
name = "exaudflib_output_path_header",
Expand Down Expand Up @@ -55,7 +47,7 @@ cc_library(
"@exaudfclient_base//exaudflib:header",
"@exaudfclient_base//utils:utils",
"@exaudfclient_base//exaudflib:exaudflib-deps",
] + VM_ENABLED_DEPS + VM_PYTHON3_DEPS,
] + VM_ENABLED_DEPS,
defines = VM_ENABLED_DEFINES,
data = ["@exaudfclient_base//:libexaudflib_complete.so"],
)
Expand All @@ -77,8 +69,7 @@ cc_binary(
## With this binary we simulate an error in our build system, that is a direct depedency to protobuf/zmq,
## which then must be detected with the linker namespace tests:
## test/linker_namespace_sanity/linker_namespace_sanity.py checks the wrong configuration
## Besides this the test under test/python3/all/linker_namespace.py checks the normal build, which expects
## not to find any occurence of the dependencies (protobuf/zmq) in the primary linker namespace.
## The normal build should not expose protobuf/zmq in the primary linker namespace.
##
## We need to explicitly declare the dependency of protobuf/zmq here, as the exaudflib is a static lib (//exaudflib:exaudflib)
## and hence does not contain dependency information. We cannot declare the shared lib (:exaudflib_complete.so)
Expand All @@ -99,8 +90,8 @@ cc_binary(
data = ["@exaudfclient_base//:libexaudflib_complete.so"],
)

# Workarround for the hardcoded paths in exaudfclient for libexaudflib_complete.so and python_ext_dataframe.cc
# - libexaudflib_complete.so and python_ext_dataframe.cc get dynamically loaded, therefore the exaudfclient needs to know their paths
# Workarround for the hardcoded paths in udf-runner-cpp for libexaudflib_complete.so
# - libexaudflib_complete.so gets dynamically loaded, therefore the udf-runner-cpp needs to know their path
# - Most flexible way to provides these paths would environment variables
# - The exasol database can't provide these paths, because they depend on the container
# - A workarround to provide these paths would be wrapper bash script which set these environment variables
Expand Down
22 changes: 0 additions & 22 deletions udf-runner-cpp/v1/MODULE.bazel
Original file line number Diff line number Diff line change
Expand Up @@ -4,31 +4,9 @@ bazel_dep(name = "exaudfclient_base", version = "1.0.0")
#For now, the Bazel Modul "exaudfclient_base" is stored in subdirectory "base".
#Later we might fetch it via Http or Git (after splitting up script-languages repository)
local_path_override(module_name="exaudfclient_base", path="base")
bazel_dep(name = "rules_jvm_external", version = "6.2")

numpy_local_repository = use_repo_rule("@exaudfclient_base//:python_repository.bzl", "numpy_local_repository")
numpy_local_repository(name = "numpy")

python_local_repository = use_repo_rule("@exaudfclient_base//:python_repository.bzl", "python_local_repository")
python_local_repository(name = "python3", python_version="python3")

zmq_local_repository = use_repo_rule("@exaudfclient_base//:zmq_repository.bzl", "zmq_local_repository")
zmq_local_repository(name = "zmq")

protobuf_local_repository = use_repo_rule("@exaudfclient_base//:protobuf_repository.bzl", "protobuf_local_repository")
protobuf_local_repository(name = "protobuf")

java_local_repository = use_repo_rule("@exaudfclient_base//:java_repository.bzl", "java_local_repository")
java_local_repository(name = "java")


maven = use_extension("@rules_jvm_external//:extensions.bzl", "maven")
maven.install(
artifacts = [
"com.exasol:udf-api-java:1.0.5",
],
repositories = [
"https://repo1.maven.org/maven2",
],
)
use_repo(maven, "maven")
28 changes: 11 additions & 17 deletions udf-runner-cpp/v1/README.md
Original file line number Diff line number Diff line change
@@ -1,17 +1,16 @@
# What is the exaudfclient?
# What is the udf-runner-cpp?

The exaudfclient connects to the database via [ZeroMQ](http://zeromq.org/) and fetches the tuples which then get processed by the user-defined functions (UDFs). Currently, the exaudfclient supports UDFs in the language Python, Java and R. Further languages can be integrated via language binding between C/C++ and the desired langauge. Python 3, Java and R use [SWIG](http://www.swig.org/) for the language binding.
The udf-runner-cpp connects to the database via [ZeroMQ](https://zeromq.org/) and fetches the tuples which then get processed by the user-defined functions (UDFs). This repository contains the C++ runner, the benchmark and streaming VM support.

# How to build the exaudfclient?
# How to build the udf-runner-cpp?

## Prerequisites

For the build system:

- Open JDK 11
- bazel-7.2.1 for more details see [Bazel documentation](https://docs.bazel.build/versions/master/install.html)

The exaudfclient was tested with the following versions of its dependencies:
The udf-runner-cpp is tested with the following versions of its dependencies:

- swig-2.0.4 or swig-3.0.12
- protobuf 3.12.4
Expand All @@ -21,14 +20,11 @@ The exaudfclient was tested with the following versions of its dependencies:

For the language support:

- Python 3.10 for pythoncontainer
- for Python 3 the build requires [Numpy](https://www.numpy.org/) and [Pandas](https://pandas.pydata.org/) in addition for the Pandas Dataframe Support
- OpenJDK 11 for javacontainer
- R 4.4 for the rcontainer
- no additional language-specific tool-chains are required for the retained runner modes in this repository.

## Start a build

The exaudfclient is a multi-language projects. Therefore, we are using [Bazel](https://docs.bazel.build/versions/master/bazel-overview.html) as build system, because it provide build support for many languages and allows to mix these languages. Because the exaudfclient has language bindings to Python 2/3, Java and R, we need specify where Bazel can find the correponding library- and header-files. This is done by Environment Variables.
The udf-runner-cpp is built with [Bazel](https://docs.bazel.build/versions/master/bazel-overview.html). In this repository, the remaining build-time environment variables are used for protobuf and zeromq discovery.
Comment thread
kratz00 marked this conversation as resolved.

For executing the build locally, you can use the script

Expand All @@ -44,11 +40,9 @@ and set the Environment Variables via Docker.

Both build script can receive parameters, such as Bazel commandline parameter, Bazel define (--define {key}={value}) and targets.

With Bazel defines you can specify which language support is actually compiled into you exaudfclient executbale. The currently supported defines are
With Bazel defines you can specify which retained VM support is compiled into your udf-runner-cpp executable. The currently supported defines are

--define java=true
--define r=true
--define python=true
--define bash=true
--define benchmark=true # This language is only for test and development purpose and benchmarks the performance of the C++ Implementation


Expand All @@ -60,11 +54,11 @@ Bazel allows to query the dependencies of a target. Furthermore, it can export t

visualize_deps.sh <targets>

# How is the exaudfclient structured?
# How is the udf-runner-cpp structured?

The exaudfclient consists mainly out of three parts the main function in [exa_udfclient.cc](exa_udfclient.cc), the libexaudf and the language implementations. The first part the main function actually only loads the two other parts. However, in this case it is important how it loads the two other parts, because we need the libexaudf in a different linker namespace than the language implementation to prevent library conflicts. The libexaudf uses [ZeroMQ](http://zeromq.org/) and [Protobuf](https://developers.google.com/protocol-buffers/) to communicate with the Exsol Database, but UDFs could be use the same libraries in a different version which would lead to library conflict. The following figure shows the dependencies between the components.
The udf-runner-cpp consists mainly of three parts: the main function in [exa_udfclient.cc](exa_udfclient.cc), the libexaudf, and the retained language implementations. The first part actually only loads the two other parts. However, in this case it is important how it loads the two other parts, because we need the libexaudf in a different linker namespace than the language implementation to prevent library conflicts. The libexaudf uses [ZeroMQ](https://zeromq.org/) and [Protobuf](https://developers.google.com/protocol-buffers/) to communicate with the Exasol database, but UDFs could use the same libraries in a different version which would lead to library conflicts. The following figure shows the dependencies between the components.

![exaudfclient dependencies](docs/exaudfclient.png)
![udf-runner-cpp dependencies](docs/exaudfclient.png)

The usage of multiple linker namespace requires some precautions in the build process and in the implementation.

Expand Down
2 changes: 0 additions & 2 deletions udf-runner-cpp/v1/base/.bazelrc
Original file line number Diff line number Diff line change
@@ -1,7 +1,5 @@
build --lockfile_mode=off --copt='-std=c++17' --force_pic --action_env=PROTOBUF_BIN --action_env=PROTOBUF_LIBRARY_PREFIX --action_env=PROTOBUF_INCLUDE_PREFIX
build:benchmark --define benchmark=true
build:java --define java=true --action_env=JAVA_PREFIX
build:python --define python=true --action_env=NUMPY_PREFIX --action_env=PYTHON3_SYSPATH --action_env=PYTHON3_PREFIX --action_env=PYTHON3_VERSION
build:debug-build --sandbox_debug --config=verbose
build:no-symlinks --symlink_prefix=/
build:asan --strip=never
Expand Down
10 changes: 0 additions & 10 deletions udf-runner-cpp/v1/base/BUILD
Original file line number Diff line number Diff line change
Expand Up @@ -12,16 +12,6 @@ config_setting(
define_values = {"benchmark": "true"},
)

config_setting(
name = "python",
define_values = {"python": "true"},
)

config_setting(
name = "java",
define_values = {"java": "true"},
)

config_setting(
name = "bash",
define_values = {"bash": "true"},
Expand Down
32 changes: 0 additions & 32 deletions udf-runner-cpp/v1/base/MODULE.bazel
Original file line number Diff line number Diff line change
Expand Up @@ -2,41 +2,9 @@ module(name="exaudfclient_base", version = "1.0")

bazel_dep(name = "bazel_skylib", version = "1.7.1")
bazel_dep(name = "googletest", version = "1.15.0")
bazel_dep(name = "rules_jvm_external", version = "6.2")

# The following is necessary to build the UDF client for Java
# Since Bazel >8 the Python hermetic build rules must not run as root
# However, since the UDF client is built as root in a docker container
# we must disable this behavior. The only way is to configure the Python hermetic toolchain
bazel_dep(name = "rules_python", version = "1.7.0")

python = use_extension("@rules_python//python/extensions:python.bzl", "python")
python.defaults(python_version = "3.11")
python.toolchain(python_version = "3.11", ignore_root_user_error = True,)


numpy_local_repository = use_repo_rule("@exaudfclient_base//:python_repository.bzl", "numpy_local_repository")
numpy_local_repository(name = "numpy")

python_local_repository = use_repo_rule("@exaudfclient_base//:python_repository.bzl", "python_local_repository")
python_local_repository(name = "python3", python_version="python3")

zmq_local_repository = use_repo_rule("@exaudfclient_base//:zmq_repository.bzl", "zmq_local_repository")
zmq_local_repository(name = "zmq")

protobuf_local_repository = use_repo_rule("@exaudfclient_base//:protobuf_repository.bzl", "protobuf_local_repository")
protobuf_local_repository(name = "protobuf")

java_local_repository = use_repo_rule("@exaudfclient_base//:java_repository.bzl", "java_local_repository")
java_local_repository(name = "java")

maven = use_extension("@rules_jvm_external//:extensions.bzl", "maven")
maven.install(
artifacts = [
"com.exasol:udf-api-java:1.0.5",
],
repositories = [
"https://repo1.maven.org/maven2",
],
)
use_repo(maven, "maven")
1 change: 0 additions & 1 deletion udf-runner-cpp/v1/base/exaudfclient.template.sh
Original file line number Diff line number Diff line change
Expand Up @@ -3,5 +3,4 @@
SCRIPT_DIR="$(dirname "$(readlink -f "${BASH_SOURCE[0]}")")"
echo "Changing to script directory $SCRIPT_DIR"
cd "$SCRIPT_DIR" || return 1
export LIBPYEXADATAFRAME_DIR="$SCRIPT_DIR/external/exaudfclient_base+/python/python3"
export LD_LIBRARY_PATH="/opt/conda/cuda-compat/:$LD_LIBRARY_PATH" #Temporary hack for the Cuda ML flavor(s)
53 changes: 0 additions & 53 deletions udf-runner-cpp/v1/base/java_repository.bzl

This file was deleted.

Loading