From 939148fc089399d5869527967e06433fd5de25dc Mon Sep 17 00:00:00 2001 From: Ravindranath Kakarla Date: Fri, 22 Jul 2022 17:05:16 -0700 Subject: [PATCH] Create a native C library from Glue Schema Registry Java library --- native-schema-registry/README.md | 16 ++ native-schema-registry/c/.clang-tidy | 12 + native-schema-registry/c/CMakeLists.txt | 35 +++ native-schema-registry/c/README.md | 46 ++++ .../glue_schema_registry_deserializer.h | 32 +++ .../c/include/glue_schema_registry_error.h | 54 +++++ .../c/include/glue_schema_registry_schema.h | 41 ++++ .../include/glue_schema_registry_serializer.h | 25 +++ .../c/include/memory_allocator.h | 16 ++ .../c/include/mutable_byte_array.h | 45 ++++ .../c/include/read_only_byte_array.h | 35 +++ native-schema-registry/c/src/CMakeLists.txt | 146 +++++++++++++ .../c/src/cmake/FetchAwsCommon.cmake | 12 + .../c/src/memory_allocator.c | 21 ++ native-schema-registry/c/test/CMakeLists.txt | 70 ++++++ .../c/test/cmake/CodeCoverage.cmake | 205 ++++++++++++++++++ .../c/test/glue_schema_registry_test_helper.h | 21 ++ native-schema-registry/pom.xml | 160 ++++++++++++++ .../services/schemaregistry/DataTypes.java | 131 +++++++++++ native-schema-registry/target/ignore | 1 + pom.xml | 1 + 21 files changed, 1125 insertions(+) create mode 100644 native-schema-registry/README.md create mode 100644 native-schema-registry/c/.clang-tidy create mode 100644 native-schema-registry/c/CMakeLists.txt create mode 100644 native-schema-registry/c/README.md create mode 100644 native-schema-registry/c/include/glue_schema_registry_deserializer.h create mode 100644 native-schema-registry/c/include/glue_schema_registry_error.h create mode 100644 native-schema-registry/c/include/glue_schema_registry_schema.h create mode 100644 native-schema-registry/c/include/glue_schema_registry_serializer.h create mode 100644 native-schema-registry/c/include/memory_allocator.h create mode 100644 native-schema-registry/c/include/mutable_byte_array.h create mode 100644 native-schema-registry/c/include/read_only_byte_array.h create mode 100644 native-schema-registry/c/src/CMakeLists.txt create mode 100644 native-schema-registry/c/src/cmake/FetchAwsCommon.cmake create mode 100644 native-schema-registry/c/src/memory_allocator.c create mode 100644 native-schema-registry/c/test/CMakeLists.txt create mode 100644 native-schema-registry/c/test/cmake/CodeCoverage.cmake create mode 100644 native-schema-registry/c/test/glue_schema_registry_test_helper.h create mode 100644 native-schema-registry/pom.xml create mode 100644 native-schema-registry/src/main/java/com/amazonaws/services/schemaregistry/DataTypes.java create mode 100644 native-schema-registry/target/ignore diff --git a/native-schema-registry/README.md b/native-schema-registry/README.md new file mode 100644 index 00000000..b12e9063 --- /dev/null +++ b/native-schema-registry/README.md @@ -0,0 +1,16 @@ +# Native Schema Registry + +This module provides a native shared library (.so, .dll) version of the AWS Glue Schema Registry SerDes. +It uses GraalVM to generate the shared library. + +## Build + +Requires GraalVM (21.0+) with native-image support. + +The C data types module needs to be built before building the Java module. + +```asm +cd c && cmake -S. -Bbuild +cd build && cmake --build . --target native_schema_registry_c_data_types +cd ../../ && mvn package -P native-image +``` \ No newline at end of file diff --git a/native-schema-registry/c/.clang-tidy b/native-schema-registry/c/.clang-tidy new file mode 100644 index 00000000..2564fabb --- /dev/null +++ b/native-schema-registry/c/.clang-tidy @@ -0,0 +1,12 @@ +--- +Checks: 'clang-diagnostic-*,clang-analyzer-*,readability-*,modernize-*,bugprone-*,misc-*,google-runtime-int,llvm-header-guard,fuchsia-restrict-system-includes,-clang-analyzer-valist.Uninitialized,-clang-analyzer-security.insecureAPI.rand,-clang-analyzer-alpha.*,-readability-magic-numbers,-readability-non-const-parameter,-readability-avoid-const-params-in-decls,-readability-else-after-return,-readability-isolate-declaration,-readability-uppercase-literal-suffix,-bugprone-sizeof-expression' +WarningsAsErrors: '*' +HeaderFilterRegex: '.*\.[h]$' +FormatStyle: 'file' +CheckOptions: + - key: readability-braces-around-statements.ShortStatementLines + value: '1' + - key: google-runtime-int.TypeSuffix + value: '_t' + - key: fuchsia-restrict-system-includes.Includes + value: '*,-stdint.h,-stdbool.h,-assert.h' diff --git a/native-schema-registry/c/CMakeLists.txt b/native-schema-registry/c/CMakeLists.txt new file mode 100644 index 00000000..b504bf88 --- /dev/null +++ b/native-schema-registry/c/CMakeLists.txt @@ -0,0 +1,35 @@ +cmake_minimum_required(VERSION 3.19) +IF (APPLE) + #Defaults to Apple Compile. Explicitly install and set to gcc. + set(CMAKE_C_COMPILER gcc) +ENDIF() +project(native_schema_registry_c C) +set(CMAKE_C_STANDARD 99) + +##Global variables +#Path to GraalVM generated shared library +set(LIB_NATIVE_SCHEMA_REGISTRY_PATH "${PROJECT_SOURCE_DIR}/../target") +set(LIB_NATIVE_SCHEMA_REGISTRY_LIBRARY_NAME_PREFIX libnativeschemaregistry) +##OS Specific variables +IF (WIN32) + set(LIB_NATIVE_SCHEMA_REGISTRY_LIBRARY_NAME ${LIB_NATIVE_SCHEMA_REGISTRY_LIBRARY_NAME_PREFIX}.dll) + set(LIB_NATIVE_SCHEMA_REGISTRY_LIBRARY_OBJ_NAME ${LIB_NATIVE_SCHEMA_REGISTRY_LIBRARY_NAME_PREFIX}.lib) +ELSEIF(APPLE) + set(LIB_NATIVE_SCHEMA_REGISTRY_LIBRARY_NAME ${LIB_NATIVE_SCHEMA_REGISTRY_LIBRARY_NAME_PREFIX}.dylib) +ELSE() + set(LIB_NATIVE_SCHEMA_REGISTRY_LIBRARY_NAME ${LIB_NATIVE_SCHEMA_REGISTRY_LIBRARY_NAME_PREFIX}.so) +ENDIF() + +set(DATA_TYPES_MODULE_NAME native_schema_registry_c_data_types) +set(SERDE_MODULE_NAME native_schema_registry_c) +set(AWS_COMMON_MEMALLOC aws_common_memalloc) +set(NATIVE_SCHEMA_REGISTRY_MODULE_NAME libnativeschemaregistry) +set(CMAKE_WINDOWS_EXPORT_ALL_SYMBOLS ON) + +include_directories("include") +include_directories(${LIB_NATIVE_SCHEMA_REGISTRY_PATH}) + +add_subdirectory("src") +include (CTest) +enable_testing() +add_subdirectory("test") \ No newline at end of file diff --git a/native-schema-registry/c/README.md b/native-schema-registry/c/README.md new file mode 100644 index 00000000..81d7422a --- /dev/null +++ b/native-schema-registry/c/README.md @@ -0,0 +1,46 @@ +# Native Schema Registry in C + +This module provides a C language based API for the schema registry serializer / de-serializers. + +## Build +We use CMake to build the targets in this module. + +### Compile +```asm +#Run in c directory + +cmake -S. -Bbuild +cd build +cmake --build . + +#### Clean +cmake --build . --target clean +``` +### Testing +```asm +ctest . +#Re-run failed tests with verbose output +ctest --rerun-failed --output-on-failure +``` + +### Code Analysis +Code is statically analyzed using clang-tidy. + +### Coverage +Code coverage checks using gcov and lcov and fail if the coverage is below threshold. + +#### Installation +You might have to install these modules using your OS package manager. + +### Sanitizers +We use address,leak sanitizers to detect memory leaks and any potential issues during build. As of now, they only work on Linux. + +### Platform Support + +TBD + +## License + +**Project License** [Apache License Version 2.0](https://github.com/awslabs/aws-glue-schema-registry/blob/master/LICENSE.txt) + +N.B.: Although this repository is released under the Apache-2.0 license, its build dependencies include the third party Swig project. The Swig project's licensing includes the GPL-3.0 license. diff --git a/native-schema-registry/c/include/glue_schema_registry_deserializer.h b/native-schema-registry/c/include/glue_schema_registry_deserializer.h new file mode 100644 index 00000000..8ae881c7 --- /dev/null +++ b/native-schema-registry/c/include/glue_schema_registry_deserializer.h @@ -0,0 +1,32 @@ +#ifndef GLUE_SCHEMA_REGISTRY_DESERIALIZER_H +#define GLUE_SCHEMA_REGISTRY_DESERIALIZER_H + +#include "glue_schema_registry_schema.h" +#include "glue_schema_registry_error.h" +#include "mutable_byte_array.h" +#include "read_only_byte_array.h" +#include + +typedef struct glue_schema_registry_deserializer { + //This is used for storing the instance context. Currently, being used for managing GraalVM instance. + void *instance_context; +} glue_schema_registry_deserializer; + +glue_schema_registry_deserializer *new_glue_schema_registry_deserializer(glue_schema_registry_error **p_err); + +void delete_glue_schema_registry_deserializer(glue_schema_registry_deserializer *deserializer); + +mutable_byte_array *glue_schema_registry_deserializer_decode(glue_schema_registry_deserializer *deserializer, + read_only_byte_array *array, + glue_schema_registry_error **p_err); + +glue_schema_registry_schema * +glue_schema_registry_deserializer_decode_schema(glue_schema_registry_deserializer *deserializer, + read_only_byte_array *array, + glue_schema_registry_error **p_err); + +bool glue_schema_registry_deserializer_can_decode(glue_schema_registry_deserializer *deserializer, + read_only_byte_array *array, + glue_schema_registry_error **p_err); + +#endif //GLUE_SCHEMA_REGISTRY_DESERIALIZER_H diff --git a/native-schema-registry/c/include/glue_schema_registry_error.h b/native-schema-registry/c/include/glue_schema_registry_error.h new file mode 100644 index 00000000..d78f537d --- /dev/null +++ b/native-schema-registry/c/include/glue_schema_registry_error.h @@ -0,0 +1,54 @@ +#ifndef NATIVE_SCHEMA_REGISTRY_GLUE_SCHEMA_REGISTRY_ERROR_H +#define NATIVE_SCHEMA_REGISTRY_GLUE_SCHEMA_REGISTRY_ERROR_H + +#include + +//Error codes are arbitrarily listed from 5000. No specific reason. +#define ERR_CODE_INVALID_STATE 5000 +#define ERR_CODE_NULL_PARAMETERS 5001 +#define ERR_CODE_GRAALVM_INIT_EXCEPTION 5002 +#define ERR_CODE_GRAALVM_TEARDOWN_EXCEPTION 5003 +#define ERR_CODE_INVALID_PARAMETERS 5004 +#define ERR_CODE_RUNTIME_ERROR 5005 + +//TODO: Improve error reporting to respect logging levels. +#define log_warn(msg, code) fprintf(stderr, "WARN: %s, Code: %d\n", msg, code) + +#define MAX_ERROR_MSG_LEN 10000 + +/** Defines the glue_schema_registry_error structure for holding error messages and codes + * resulting from function executions. + */ +typedef struct glue_schema_registry_error { + char * msg; + int code; +} glue_schema_registry_error; + +glue_schema_registry_error * new_glue_schema_registry_error(const char * err_msg, int err_code); + +void delete_glue_schema_registry_error(glue_schema_registry_error *error); + +//Copies the given error's msg into dst array trimming the size as necessary. +void glue_schema_registry_error_get_msg(glue_schema_registry_error *error, char *dst, size_t len); + +/** + * Creates an instance of glue_schema_registry_error and writes it to the given + * glue_schema_registry_error pointer holder (*p_err). It is expected that *p_err + * is initialized by caller. + * @param p_err Initialized glue_schema_registry_error pointer holder. + * @param msg Error message to write. + * @param code Non-zero error code. + */ +void throw_error(glue_schema_registry_error **p_err, const char *msg, int code); + +/** + * Creates a pointer to hold an instance of glue_schema_registry_error + */ +glue_schema_registry_error **new_glue_schema_registry_error_holder(void); + +/** + * Deletes the pointer holder of glue_schema_registry_error and it's content. + */ +void delete_glue_schema_registry_error_holder(glue_schema_registry_error **p_err); + +#endif //NATIVE_SCHEMA_REGISTRY_GLUE_SCHEMA_REGISTRY_ERROR_H diff --git a/native-schema-registry/c/include/glue_schema_registry_schema.h b/native-schema-registry/c/include/glue_schema_registry_schema.h new file mode 100644 index 00000000..7ca5ea43 --- /dev/null +++ b/native-schema-registry/c/include/glue_schema_registry_schema.h @@ -0,0 +1,41 @@ +#ifndef GLUE_SCHEMA_REGISTRY_SCHEMA_H +#define GLUE_SCHEMA_REGISTRY_SCHEMA_H + +#include "glue_schema_registry_error.h" + +/* + * Glue Schema Registry Schema structure that represents + * schema object required by Glue Schema Registry Serializers / De-serializers. + */ +typedef struct glue_schema_registry_schema { + //String name of the schema + char * schema_name; + + //Complete definition of the schema as String + char * schema_def; + + //Data format name, JSON, AVRO, PROTOBUF as String + char * data_format; + +} glue_schema_registry_schema; + +//Creates a new instance of glue_schema_registry_schema +glue_schema_registry_schema *new_glue_schema_registry_schema( + const char * schema_name, + const char * schema_def, + const char * data_format, + glue_schema_registry_error ** p_err +); + +//Deletes the glue schema registry schema. +void delete_glue_schema_registry_schema(glue_schema_registry_schema * schema); + +//Gets different attributes from glue_schema_registry_schema instance. +//These getter methods are translated into "Getter" methods in target languages. +const char * glue_schema_registry_schema_get_schema_name(glue_schema_registry_schema * schema); + +const char * glue_schema_registry_schema_get_schema_def(glue_schema_registry_schema * schema); + +const char * glue_schema_registry_schema_get_data_format(glue_schema_registry_schema * schema); + +#endif //GLUE_SCHEMA_REGISTRY_SCHEMA_H \ No newline at end of file diff --git a/native-schema-registry/c/include/glue_schema_registry_serializer.h b/native-schema-registry/c/include/glue_schema_registry_serializer.h new file mode 100644 index 00000000..cf43a44f --- /dev/null +++ b/native-schema-registry/c/include/glue_schema_registry_serializer.h @@ -0,0 +1,25 @@ +#ifndef GLUE_SCHEMA_REGISTRY_SERIALIZER_H +#define GLUE_SCHEMA_REGISTRY_SERIALIZER_H + +#include "glue_schema_registry_schema.h" +#include "glue_schema_registry_error.h" +#include "mutable_byte_array.h" +#include "read_only_byte_array.h" + +typedef struct glue_schema_registry_serializer { + //This is used for storing the instance context. Currently being used for managing GraalVM instance. + void *instance_context; +} glue_schema_registry_serializer; + +glue_schema_registry_serializer *new_glue_schema_registry_serializer(glue_schema_registry_error **p_err); + +void delete_glue_schema_registry_serializer(glue_schema_registry_serializer *serializer); + +//Encodes the GSR Schema with a byte array. +mutable_byte_array *glue_schema_registry_serializer_encode(glue_schema_registry_serializer *serializer, + read_only_byte_array * array, + const char * transport_name, + glue_schema_registry_schema *gsr_schema, + glue_schema_registry_error **p_err); + +#endif //GLUE_SCHEMA_REGISTRY_SERIALIZER_H diff --git a/native-schema-registry/c/include/memory_allocator.h b/native-schema-registry/c/include/memory_allocator.h new file mode 100644 index 00000000..091c50b5 --- /dev/null +++ b/native-schema-registry/c/include/memory_allocator.h @@ -0,0 +1,16 @@ +#ifndef NATIVE_SCHEMA_REGISTRY_MEMORY_ALLOCATOR_H +#define NATIVE_SCHEMA_REGISTRY_MEMORY_ALLOCATOR_H + +#include + +/* + * Wrapper over AWS SDK Common memory allocator. + */ + +void *aws_common_malloc(size_t size); + +void *aws_common_calloc(size_t count, size_t size); + +void aws_common_free(void *ptr); + +#endif //NATIVE_SCHEMA_REGISTRY_MEMORY_ALLOCATOR_H diff --git a/native-schema-registry/c/include/mutable_byte_array.h b/native-schema-registry/c/include/mutable_byte_array.h new file mode 100644 index 00000000..0c92184c --- /dev/null +++ b/native-schema-registry/c/include/mutable_byte_array.h @@ -0,0 +1,45 @@ +#ifndef MUTABLE_BYTE_ARRAY_H +#define MUTABLE_BYTE_ARRAY_H +#include +#include "glue_schema_registry_error.h" + +//Integer.MAX_VALUE in Java +//This gives ~2.1Gb limit on a record. +#define MAX_BYTES_LIMIT 2147483647 +/** +* A mutable byte array that allows write / updating bytes in a fixed array of size `max_len`. +*/ +typedef struct mutable_byte_array { + unsigned char * data; + size_t max_len; +} mutable_byte_array; + +/** + * Initializes a mutable byte array of size `len` + * The data is initially set to '0' + * Caller can optionally provide pointer holder to glue_schema_registry_error to read error messages. + */ +mutable_byte_array * new_mutable_byte_array(size_t len, glue_schema_registry_error **p_err); + +/** + * Free the data and the pointer to the mutable byte array. + */ +void delete_mutable_byte_array(mutable_byte_array * array); + +/** + * Get the reference to the array contents. + */ +unsigned char * mutable_byte_array_get_data(mutable_byte_array * array); + +/** + * Writes a single byte at given index in the byte array. + */ +void mutable_byte_array_write(mutable_byte_array * array, size_t index, unsigned char byte, + glue_schema_registry_error **p_err); + +/** + * Return the len of the byte-array + */ +size_t mutable_byte_array_get_max_len(mutable_byte_array * array); + +#endif //MUTABLE_BYTE_ARRAY_H diff --git a/native-schema-registry/c/include/read_only_byte_array.h b/native-schema-registry/c/include/read_only_byte_array.h new file mode 100644 index 00000000..8f890576 --- /dev/null +++ b/native-schema-registry/c/include/read_only_byte_array.h @@ -0,0 +1,35 @@ +#ifndef READ_ONLY_BYTE_ARRAY_H +#define READ_ONLY_BYTE_ARRAY_H +#include +#include "glue_schema_registry_error.h" + +typedef struct read_only_byte_array { + unsigned char * data; + size_t len; +} read_only_byte_array; + +/** + * Creates a read-only byte array that points to given memory location to + * provide a view over the data. Attempts to modify the data can result in + * unintended consequences or crashes. + * The caller must guarantee the memory is valid and is of exactly `len` + * Caller can optionally provide pointer holder to glue_schema_registry_error to read error messages. + */ +read_only_byte_array * new_read_only_byte_array(unsigned char *data, size_t len, glue_schema_registry_error **p_err); + +/** + * Deletes the byte array instance but not the underlying data. + */ +void delete_read_only_byte_array(read_only_byte_array * array); + +/** + * Gets the reference to data pointed by this array. + */ +unsigned char * read_only_byte_array_get_data(read_only_byte_array * array); + +/** + * Gets the len of the data being pointed by this array. + */ +size_t read_only_byte_array_get_len(read_only_byte_array * array); + +#endif //READ_ONLY_BYTE_ARRAY_H \ No newline at end of file diff --git a/native-schema-registry/c/src/CMakeLists.txt b/native-schema-registry/c/src/CMakeLists.txt new file mode 100644 index 00000000..0b80e3d7 --- /dev/null +++ b/native-schema-registry/c/src/CMakeLists.txt @@ -0,0 +1,146 @@ +include(cmake/FetchAwsCommon.cmake) + +#TODO: Disable coverage / debug for production builds. +if (CMAKE_SYSTEM_NAME MATCHES "^(Linux)$") + list(APPEND TEST_COVERAGE "-ftest-coverage -fprofile-arcs") + set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} ${TEST_COVERAGE} -g -O0 -Wall") + set(CMAKE_C_CLANG_TIDY clang-tidy -checks=-*,readability-*) +endif() + +add_library(${AWS_COMMON_MEMALLOC} SHARED memory_allocator.c) +target_link_libraries(${AWS_COMMON_MEMALLOC} PRIVATE ${AWS_C_COMMON}) + +#Adding modules in the build order. +add_library( + ${DATA_TYPES_MODULE_NAME} SHARED + glue_schema_registry_schema.c + read_only_byte_array.c + mutable_byte_array.c + glue_schema_registry_error.c +) +add_custom_command( + TARGET ${DATA_TYPES_MODULE_NAME} + POST_BUILD + COMMAND ${CMAKE_COMMAND} -E copy $ ${LIB_NATIVE_SCHEMA_REGISTRY_PATH}/ + COMMAND ${CMAKE_COMMAND} -E copy $ ${LIB_NATIVE_SCHEMA_REGISTRY_PATH}/ +) + +#Add reference to the GraalVM generated Native schema registry module. +#First, fix the include path in GraalVM generated header file. +execute_process(COMMAND sed -ie "s//\"graal_isolate.h\"/" ${LIB_NATIVE_SCHEMA_REGISTRY_PATH}/libnativeschemaregistry.h) +add_library( + ${NATIVE_SCHEMA_REGISTRY_MODULE_NAME} SHARED + IMPORTED +) +set_target_properties( + ${NATIVE_SCHEMA_REGISTRY_MODULE_NAME} + PROPERTIES + IMPORTED_LOCATION "${LIB_NATIVE_SCHEMA_REGISTRY_PATH}/${LIB_NATIVE_SCHEMA_REGISTRY_LIBRARY_NAME}" + IMPORTED_IMPLIB "${LIB_NATIVE_SCHEMA_REGISTRY_PATH}/${LIB_NATIVE_SCHEMA_REGISTRY_LIBRARY_OBJ_NAME}" + INTERFACE_INCLUDE_DIRECTORIES "${LIB_NATIVE_SCHEMA_REGISTRY_PATH}" +) + +add_library( + ${SERDE_MODULE_NAME} SHARED + glue_schema_registry_serializer.c + glue_schema_registry_deserializer.c +) + +target_link_libraries( + ${DATA_TYPES_MODULE_NAME} + ${AWS_COMMON_MEMALLOC} +) + +target_link_libraries( + ${SERDE_MODULE_NAME} + ${AWS_COMMON_MEMALLOC} + ${DATA_TYPES_MODULE_NAME} + ${NATIVE_SCHEMA_REGISTRY_MODULE_NAME} +) + +##Swig compilation +set(CMAKE_SWIG_FLAGS) +find_package(SWIG REQUIRED) +include(UseSWIG) + +file( + GLOB GsrSerDeSrc + "swig/glue_schema_registry_serde.i" +) + +#No need to run CLang Tidy on Swig generated code. +unset(CMAKE_C_CLANG_TIDY) + +#####CSharp +set(CSHARP_MODULE_NAME GsrSerDeCsGen) +set(CSHARP_ROOT_PATH ${PROJECT_SOURCE_DIR}/../csharp/AWSGsrSerDe) +set(CSHARP_SOURCE_PATH ${CSHARP_ROOT_PATH}/AWSGsrSerDe/) +set(CSHARP_GEN_LIB_PATH ${CSHARP_ROOT_PATH}/Libs/) +swig_add_library( + ${CSHARP_MODULE_NAME} + TYPE SHARED + LANGUAGE csharp + OUTPUT_DIR "${CSHARP_SOURCE_PATH}" + SOURCES ${GsrSerDeSrc} +) +set_target_properties( + ${CSHARP_MODULE_NAME} + PROPERTIES + INCLUDE_DIRECTORIES "${PROJECT_SOURCE_DIR}/include/" + SWIG_USE_TARGET_INCLUDE_DIRECTORIES TRUE +) +swig_link_libraries( + ${CSHARP_MODULE_NAME} + PUBLIC + ${DATA_TYPES_MODULE_NAME} + ${SERDE_MODULE_NAME} + ${AWS_COMMON_MEMALLOC} + ${NATIVE_SCHEMA_REGISTRY_MODULE_NAME} +) +##TODO: Fix this during release. We should segregate Debug and Release +##Copying built libraries to CSharp project +add_custom_command( + TARGET ${CSHARP_MODULE_NAME} + POST_BUILD + COMMAND ${CMAKE_COMMAND} -E copy $ ${CSHARP_GEN_LIB_PATH}/ + COMMAND ${CMAKE_COMMAND} -E copy $ ${CSHARP_GEN_LIB_PATH}/ + COMMAND ${CMAKE_COMMAND} -E copy $ ${CSHARP_GEN_LIB_PATH}/ + COMMAND ${CMAKE_COMMAND} -E copy $ ${CSHARP_GEN_LIB_PATH}/ + COMMAND ${CMAKE_COMMAND} -E copy $ ${CSHARP_GEN_LIB_PATH}/ +) + +####Python +find_package(PythonLibs REQUIRED) +set(PYTHON_MODULE_NAME GsrSerDePyGen) +set(PYTHON_ROOT_PATH ${PROJECT_SOURCE_DIR}/../python/PyGsrSerDe) +set(PYTHON_SOURCE_PATH ${PYTHON_ROOT_PATH}/) +set(PYTHON_GEN_LIB_PATH ${PYTHON_ROOT_PATH}) +swig_add_library( + ${PYTHON_MODULE_NAME} + TYPE SHARED + LANGUAGE python + OUTPUT_DIR "${PYTHON_SOURCE_PATH}" + SOURCES ${GsrSerDeSrc} +) +list(APPEND PYTHON_INCLUDES + "${PROJECT_SOURCE_DIR}/include/" + #TODO: Path needs to be configurable per version and OS + "/usr/include/python3.7m/") + +target_include_directories(${PYTHON_MODULE_NAME} PUBLIC ${PYTHON_INCLUDES}) +set_target_properties( + ${PYTHON_MODULE_NAME} + PROPERTIES + SWIG_USE_TARGET_INCLUDE_DIRECTORIES TRUE +) + +##TODO: Fix this during release. We should segregate Debug and Release +##Copying built libraries to PYTHON project +add_custom_command( + TARGET ${PYTHON_MODULE_NAME} + POST_BUILD + COMMAND ${CMAKE_COMMAND} -E copy $ ${PYTHON_GEN_LIB_PATH}/ + COMMAND ${CMAKE_COMMAND} -E copy $ ${PYTHON_GEN_LIB_PATH}/ + COMMAND ${CMAKE_COMMAND} -E copy $ ${PYTHON_GEN_LIB_PATH}/ + COMMAND ${CMAKE_COMMAND} -E copy $ ${PYTHON_GEN_LIB_PATH}/ +) diff --git a/native-schema-registry/c/src/cmake/FetchAwsCommon.cmake b/native-schema-registry/c/src/cmake/FetchAwsCommon.cmake new file mode 100644 index 00000000..3e27fe4b --- /dev/null +++ b/native-schema-registry/c/src/cmake/FetchAwsCommon.cmake @@ -0,0 +1,12 @@ +include(FetchContent) + +set(AWS_C_COMMON aws-c-common) + +FetchContent_Declare( + AWS_C_COMMON + GIT_REPOSITORY https://github.com/awslabs/aws-c-common.git + GIT_TAG v0.7.4 + GIT_SHALLOW 1 +) + +FetchContent_MakeAvailable(AWS_C_COMMON) \ No newline at end of file diff --git a/native-schema-registry/c/src/memory_allocator.c b/native-schema-registry/c/src/memory_allocator.c new file mode 100644 index 00000000..543245b5 --- /dev/null +++ b/native-schema-registry/c/src/memory_allocator.c @@ -0,0 +1,21 @@ +#include "memory_allocator.h" +#include "aws/common/allocator.h" + +/* + * Uses the default memory allocator from AWS SDK Common library to allocate / free memory. + */ +void *aws_common_malloc(size_t size) { + struct aws_allocator *allocator = aws_default_allocator(); + return aws_mem_acquire(allocator, size); +} + +void * aws_common_calloc(size_t count, size_t size) { + struct aws_allocator *allocator = aws_default_allocator(); + return aws_mem_calloc(allocator, count, size); +} + +void aws_common_free(void *ptr) { + struct aws_allocator *allocator = aws_default_allocator(); + aws_mem_release(allocator, ptr); +} + diff --git a/native-schema-registry/c/test/CMakeLists.txt b/native-schema-registry/c/test/CMakeLists.txt new file mode 100644 index 00000000..954d8491 --- /dev/null +++ b/native-schema-registry/c/test/CMakeLists.txt @@ -0,0 +1,70 @@ +if (CMAKE_SYSTEM_NAME MATCHES "^(Linux|Darwin)$") + list(APPEND SANITIZER_CHECKS "-fsanitize=address,undefined -fsanitize-recover=address -fno-stack-protector") +else() + #TODO: Figure out equivalent options for Windows + list(APPEND SANITIZER_CHECKS "") +endif() +set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} ${SANITIZER_CHECKS} -Wall") +include(cmake/FetchCMocka.cmake) + +set(TEST_HELPERS test_helpers) +add_library(${TEST_HELPERS} glue_schema_registry_test_helper.c) +target_link_libraries(${TEST_HELPERS} cmocka) + +##GraalVM Mock +add_library(${NATIVE_SCHEMA_REGISTRY_MODULE_NAME} libnativeschemaregistry_mock.c) +target_link_libraries(${NATIVE_SCHEMA_REGISTRY_MODULE_NAME} cmocka) + +list( + APPEND + tests + #Add tests below: + glue_schema_registry_schema_test + read_only_byte_array_test + mutable_byte_array_test + glue_schema_registry_error_test +) + +#TODO: These tests don't work on Windows and OSX due to CMake not linking the mock library. +#We have to investigate and fix these. +if (CMAKE_SYSTEM_NAME STREQUAL "Linux") + list(APPEND + tests + glue_schema_registry_serializer_test + glue_schema_registry_deserializer_test + ) +ENDIF () + +foreach (test ${tests}) + add_executable( + "${test}" + "${test}.c" + ) + target_link_libraries( + "${test}" + "${DATA_TYPES_MODULE_NAME}" + "${SERDE_MODULE_NAME}" + "${NATIVE_SCHEMA_REGISTRY_MODULE_NAME}" + "${AWS_COMMON_MEMALLOC}" + "${TEST_HELPERS}" + "cmocka" + ) + + add_test(NAME "${test}" COMMAND "${test}" ${CMAKE_CURRENT_BINARY_DIR}) +endforeach () + +add_custom_target(copy-libs-for-tests ALL + COMMAND ${CMAKE_COMMAND} -E copy $ ${CMAKE_CURRENT_BINARY_DIR}/ + COMMAND ${CMAKE_COMMAND} -E copy $ ${CMAKE_CURRENT_BINARY_DIR}/ + COMMAND ${CMAKE_COMMAND} -E copy $ ${CMAKE_CURRENT_BINARY_DIR}/ + COMMAND ${CMAKE_COMMAND} -E copy $ ${CMAKE_CURRENT_BINARY_DIR}/ + COMMAND ${CMAKE_COMMAND} -E copy $ ${CMAKE_CURRENT_BINARY_DIR}/ +) + +#Create code coverage target +if (CMAKE_SYSTEM_NAME MATCHES "^(Linux)$") + set(CMAKE_COMPILER_IS_GNUCXX 1) + include(cmake/CodeCoverage.cmake) + set(min_code_coverage 100) + setup_target_for_coverage(coverage "ctest ." coverage ${min_code_coverage}) +endif() \ No newline at end of file diff --git a/native-schema-registry/c/test/cmake/CodeCoverage.cmake b/native-schema-registry/c/test/cmake/CodeCoverage.cmake new file mode 100644 index 00000000..1e61a681 --- /dev/null +++ b/native-schema-registry/c/test/cmake/CodeCoverage.cmake @@ -0,0 +1,205 @@ +# Copyright (c) 2012 - 2015, Lars Bilke +# All rights reserved. +# +# Redistribution and use in source and binary forms, with or without modification, +# are permitted provided that the following conditions are met: +# +# 1. Redistributions of source code must retain the above copyright notice, this +# list of conditions and the following disclaimer. +# +# 2. Redistributions in binary form must reproduce the above copyright notice, +# this list of conditions and the following disclaimer in the documentation +# and/or other materials provided with the distribution. +# +# 3. Neither the name of the copyright holder nor the names of its contributors +# may be used to endorse or promote products derived from this software without +# specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND +# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +# WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR +# ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +# (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +# LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON +# ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +# SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +# +# +# +# 2012-01-31, Lars Bilke +# - Enable Code Coverage +# +# 2013-09-17, Joakim Söderberg +# - Added support for Clang. +# - Some additional usage instructions. +# +# USAGE: + +# 0. (Mac only) If you use Xcode 5.1 make sure to patch geninfo as described here: +# http://stackoverflow.com/a/22404544/80480 +# +# 1. Copy this file into your cmake modules path. +# +# 2. Add the following line to your CMakeLists.txt: +# INCLUDE(CodeCoverage) +# +# 3. Set compiler flags to turn off optimization and enable coverage: +# SET(CMAKE_CXX_FLAGS "-g -O0 -fprofile-arcs -ftest-coverage") +# SET(CMAKE_C_FLAGS "-g -O0 -fprofile-arcs -ftest-coverage") +# +# 3. Use the function SETUP_TARGET_FOR_COVERAGE to create a custom make target +# which runs your test executable and produces a lcov code coverage report: +# Example: +# SETUP_TARGET_FOR_COVERAGE( +# my_coverage_target # Name for custom target. +# test_driver # Name of the test driver executable that runs the tests. +# # NOTE! This should always have a ZERO as exit code +# # otherwise the coverage generation will not complete. +# coverage # Name of output directory. +# ) +# +# If you need to exclude additional directories from the report, specify them +# using the LCOV_REMOVE_EXTRA variable before calling SETUP_TARGET_FOR_COVERAGE. +# For example: +# +# set(LCOV_REMOVE_EXTRA "'thirdparty/*'") +# +# 4. Build a Debug build: +# cmake -DCMAKE_BUILD_TYPE=Debug .. +# make +# make my_coverage_target +# +# + +# Check prereqs +FIND_PROGRAM( GCOV_PATH gcov ) +FIND_PROGRAM( LCOV_PATH lcov ) +FIND_PROGRAM( GENHTML_PATH genhtml ) +FIND_PROGRAM( GCOVR_PATH gcovr PATHS ${CMAKE_SOURCE_DIR}/tests) + +IF(NOT GCOV_PATH) + MESSAGE(FATAL_ERROR "gcov not found! Aborting...") +ENDIF() # NOT GCOV_PATH + +IF("${CMAKE_CXX_COMPILER_ID}" MATCHES "(Apple)?[Cc]lang") + IF("${CMAKE_CXX_COMPILER_VERSION}" VERSION_LESS 3) + MESSAGE(FATAL_ERROR "Clang version must be 3.0.0 or greater! Aborting...") + ENDIF() +ELSEIF(NOT CMAKE_COMPILER_IS_GNUCXX) + MESSAGE(FATAL_ERROR "Compiler is not GNU gcc! Aborting...") +ENDIF() # CHECK VALID COMPILER + +SET(CMAKE_CXX_FLAGS_COVERAGE + "-g -O0 --coverage -fprofile-arcs -ftest-coverage" + CACHE STRING "Flags used by the C++ compiler during coverage builds." + FORCE ) +SET(CMAKE_C_FLAGS_COVERAGE + "-g -O0 --coverage -fprofile-arcs -ftest-coverage" + CACHE STRING "Flags used by the C compiler during coverage builds." + FORCE ) +SET(CMAKE_EXE_LINKER_FLAGS_COVERAGE + "" + CACHE STRING "Flags used for linking binaries during coverage builds." + FORCE ) +SET(CMAKE_SHARED_LINKER_FLAGS_COVERAGE + "" + CACHE STRING "Flags used by the shared libraries linker during coverage builds." + FORCE ) +MARK_AS_ADVANCED( + CMAKE_CXX_FLAGS_COVERAGE + CMAKE_C_FLAGS_COVERAGE + CMAKE_EXE_LINKER_FLAGS_COVERAGE + CMAKE_SHARED_LINKER_FLAGS_COVERAGE ) + +IF ( NOT (CMAKE_BUILD_TYPE STREQUAL "Debug" OR CMAKE_BUILD_TYPE STREQUAL "Coverage")) + MESSAGE( WARNING "Code coverage results with an optimized (non-Debug) build may be misleading" ) +ENDIF() # NOT CMAKE_BUILD_TYPE STREQUAL "Debug" + + +# Param _targetname The name of new the custom make target +# Param _testrunner The name of the target which runs the tests. +# MUST return ZERO always, even on errors. +# If not, no coverage report will be created! +# Param _outputname lcov output is generated as _outputname.info +# HTML report is generated in _outputname/index.html +FUNCTION(SETUP_TARGET_FOR_COVERAGE _targetname _testrunner _outputname _min_coverage_percent) + + IF(NOT LCOV_PATH) + MESSAGE(FATAL_ERROR "lcov not found! Aborting...") + ENDIF() # NOT LCOV_PATH + + IF(NOT GENHTML_PATH) + MESSAGE(FATAL_ERROR "genhtml not found! Aborting...") + ENDIF() # NOT GENHTML_PATH + + SET(coverage_info "${CMAKE_BINARY_DIR}/${_outputname}.info") + SET(coverage_cleaned "${coverage_info}.cleaned") + SET(min_coverage_percent ${_min_coverage_percent}) + + SEPARATE_ARGUMENTS(test_command UNIX_COMMAND "${_testrunner}") + + # Setup target + ADD_CUSTOM_TARGET(${_targetname} + + # Cleanup lcov + ${LCOV_PATH} --directory . --zerocounters + + # Run tests + COMMAND ${test_command} ${ARGV3} + + # Capturing lcov counters and generating report + COMMAND ${LCOV_PATH} --directory . --capture --output-file ${coverage_info} + #Fail when coverage is below 'n' + COMMAND echo "Minimum Coverage Required: ${min_coverage_percent}" + COMMAND ${LCOV_PATH} --summary ${coverage_info} --fail-under-lines ${min_coverage_percent} + COMMAND ${LCOV_PATH} --remove ${coverage_info} 'tests/*' '/usr/*' ${LCOV_REMOVE_EXTRA} --output-file ${coverage_cleaned} + COMMAND ${GENHTML_PATH} -o ${_outputname} ${coverage_cleaned} + COMMAND ${CMAKE_COMMAND} -E remove ${coverage_info} ${coverage_cleaned} + + WORKING_DIRECTORY ${CMAKE_BINARY_DIR} + COMMENT "Resetting code coverage counters to zero.\nProcessing code coverage counters and generating report." + ) + + # Show info where to find the report + ADD_CUSTOM_COMMAND(TARGET ${_targetname} POST_BUILD + COMMAND ; + COMMENT "Open ./${_outputname}/index.html in your browser to view the coverage report." + ) + +ENDFUNCTION() # SETUP_TARGET_FOR_COVERAGE + +# Param _targetname The name of new the custom make target +# Param _testrunner The name of the target which runs the tests +# Param _outputname cobertura output is generated as _outputname.xml +# Optional fourth parameter is passed as arguments to _testrunner +# Pass them in list form, e.g.: "-j;2" for -j 2 +FUNCTION(SETUP_TARGET_FOR_COVERAGE_COBERTURA _targetname _testrunner _outputname) + + IF(NOT PYTHON_EXECUTABLE) + MESSAGE(FATAL_ERROR "Python not found! Aborting...") + ENDIF() # NOT PYTHON_EXECUTABLE + + IF(NOT GCOVR_PATH) + MESSAGE(FATAL_ERROR "gcovr not found! Aborting...") + ENDIF() # NOT GCOVR_PATH + + ADD_CUSTOM_TARGET(${_targetname} + + # Run tests + ${_testrunner} ${ARGV3} + + # Running gcovr + COMMAND ${GCOVR_PATH} -x -r ${CMAKE_SOURCE_DIR} -e '${CMAKE_SOURCE_DIR}/tests/' -o ${_outputname}.xml + WORKING_DIRECTORY ${CMAKE_BINARY_DIR} + COMMENT "Running gcovr to produce Cobertura code coverage report." + ) + + # Show info where to find the report + ADD_CUSTOM_COMMAND(TARGET ${_targetname} POST_BUILD + COMMAND ; + COMMENT "Cobertura code coverage report saved in ${_outputname}.xml." + ) + +ENDFUNCTION() # SETUP_TARGET_FOR_COVERAGE_COBERTURA diff --git a/native-schema-registry/c/test/glue_schema_registry_test_helper.h b/native-schema-registry/c/test/glue_schema_registry_test_helper.h new file mode 100644 index 00000000..158bfc85 --- /dev/null +++ b/native-schema-registry/c/test/glue_schema_registry_test_helper.h @@ -0,0 +1,21 @@ +#ifndef NATIVE_SCHEMA_REGISTRY_TEST_FIXTURES_H +#define NATIVE_SCHEMA_REGISTRY_TEST_FIXTURES_H +#include "read_only_byte_array.h" +#include "mutable_byte_array.h" +#include "glue_schema_registry_schema.h" + +glue_schema_registry_schema * get_gsr_schema_fixture(void); + +read_only_byte_array * get_read_only_byte_array_fixture(void); + +mutable_byte_array * get_mut_byte_array_fixture(void); + +void assert_mutable_byte_array_eq(mutable_byte_array expected, mutable_byte_array actual); + +void assert_error_and_clear(glue_schema_registry_error **p_err, const char *msg, int code); + +void assert_gsr_schema(glue_schema_registry_schema, glue_schema_registry_schema); + +const char * get_transport_name_fixture(void); + +#endif //NATIVE_SCHEMA_REGISTRY_TEST_FIXTURES_H diff --git a/native-schema-registry/pom.xml b/native-schema-registry/pom.xml new file mode 100644 index 00000000..e8e8b56c --- /dev/null +++ b/native-schema-registry/pom.xml @@ -0,0 +1,160 @@ + + + 4.0.0 + + ${parent.groupId} + native-schema-registry + Native AWS Schema Registry + AWS Glue Schema Registry native shared library wrapper + https://aws.amazon.com/glue + ${parent.version} + jar + + + software.amazon.glue + schema-registry-parent + 1.1.10 + ../pom.xml + + + + scm:git:https://github.com/aws/aws-glue-schema-registry.git + scm:git:git@github.com:aws/aws-glue-schema-registry.git + https://github.com/awslabs/aws-glue-schema-registry.git + + + + + Apache License, Version 2.0 + http://www.apache.org/licenses/LICENSE-2.0.txt + repo + + + + + UTF-8 + 11 + 11 + 3.2.1 + 3.6.1 + 1.6.0 + 1.7.28 + 21.0.0 + 5.4.2 + + + + + software.amazon.awssdk + url-connection-client + + + + + software.amazon.glue + schema-registry-serde + ${parent.version} + + + + + org.slf4j + slf4j-api + + + + + org.slf4j + slf4j-simple + + + + org.graalvm.sdk + graal-sdk + ${graalvm.version} + provided + + + + org.graalvm.nativeimage + svm + ${graalvm.version} + provided + + + + + org.junit.jupiter + junit-jupiter + ${junit5.version} + test + + + org.mockito + mockito-junit-jupiter + test + + + + + + + org.apache.maven.plugins + maven-compiler-plugin + ${maven.compiler.plugin.version} + + + + + + + native-image + + + + org.graalvm.nativeimage + native-image-maven-plugin + ${graalvm.version} + + + + native-image + + package + + + + libnativeschemaregistry + + + --verbose + --no-fallback + --shared + -g + -H:CLibraryPath=${project.basedir} + + + + + + + + + diff --git a/native-schema-registry/src/main/java/com/amazonaws/services/schemaregistry/DataTypes.java b/native-schema-registry/src/main/java/com/amazonaws/services/schemaregistry/DataTypes.java new file mode 100644 index 00000000..59df6c32 --- /dev/null +++ b/native-schema-registry/src/main/java/com/amazonaws/services/schemaregistry/DataTypes.java @@ -0,0 +1,131 @@ +package com.amazonaws.services.schemaregistry; + +import com.oracle.svm.core.c.ProjectHeaderFile; +import org.graalvm.nativeimage.c.CContext; +import org.graalvm.nativeimage.c.function.CFunction; +import org.graalvm.nativeimage.c.struct.CField; +import org.graalvm.nativeimage.c.struct.CPointerTo; +import org.graalvm.nativeimage.c.struct.CStruct; +import org.graalvm.nativeimage.c.type.CCharPointer; +import org.graalvm.word.PointerBase; + +import java.util.Collections; +import java.util.List; +import java.util.stream.Collectors; +import java.util.stream.Stream; + +@CContext(DataTypes.HandlerDirectives.class) +public class DataTypes { + /** + * Declare headers required by the shared library. + */ + static class HandlerDirectives implements CContext.Directives { + + public static final String INCLUDE_PATH = "c/include/"; + public static final String LIB_PATH = "target/"; + //Intentionally blank. + public static final String PROJECT_NAME = ""; + + @Override + public List getLibraries() { + return Collections.singletonList("native_schema_registry_c_data_types"); + } + + @Override + public List getLibraryPaths() { + String path = ProjectHeaderFile.resolve(PROJECT_NAME, LIB_PATH).replaceAll("\"", ""); + return Collections.singletonList(path); + } + + @Override + public List getHeaderFiles() { + return Stream.of( + "glue_schema_registry_schema.h", + "read_only_byte_array.h", + "mutable_byte_array.h", + "glue_schema_registry_error.h" + ) + .map(header -> ProjectHeaderFile.resolve(PROJECT_NAME, INCLUDE_PATH + header)) + .collect(Collectors.toList()); + } + } + + /** + * Define the data types and functions to import from C headers. + */ + @CFunction("new_glue_schema_registry_schema") + public static native C_GlueSchemaRegistrySchema + newGlueSchemaRegistrySchema( + CCharPointer schemaName, + CCharPointer schemaDef, + CCharPointer dataFormat, + C_GlueSchemaRegistryErrorPointerHolder errorPointerHolder + ); + + @CStruct("glue_schema_registry_schema") + public interface C_GlueSchemaRegistrySchema extends PointerBase { + + //Read access of a field. A call to the function is replaced with a raw memory load. + @CField("schema_name") + CCharPointer getSchemaName(); + + @CField("schema_def") + CCharPointer getSchemaDef(); + + @CField("data_format") + CCharPointer getDataFormat(); + } + + @CStruct("read_only_byte_array") + public interface C_ReadOnlyByteArray extends PointerBase { + + @CField("data") + PointerBase getData(); + + @CField("len") + long getLen(); + } + + @CStruct("mutable_byte_array") + public interface C_MutableByteArray extends PointerBase { + + @CField("data") + PointerBase getData(); + + @CField("max_len") + long getMaxLen(); + } + + @CFunction("new_mutable_byte_array") + public static native C_MutableByteArray newMutableByteArray( + long maxLen, + C_GlueSchemaRegistryErrorPointerHolder errorPointerHolder + ); + + @CFunction("mutable_byte_array_write") + public static native void writeToMutableArray( + C_MutableByteArray array, + long index, + byte b, + C_GlueSchemaRegistryErrorPointerHolder errorPointerHolder + ); + + @CStruct("glue_schema_registry_error") + public interface C_GlueSchemaRegistryError extends PointerBase { + + //Read access of a field. A call to the function is replaced with a raw memory load. + @CField("msg") + CCharPointer getErrMsg(); + + @CField("code") + int getCode(); + } + + @CPointerTo(value = C_GlueSchemaRegistryError.class) + public interface C_GlueSchemaRegistryErrorPointerHolder extends PointerBase { + void write(C_GlueSchemaRegistryError value); + } + + @CFunction("throw_error") + public static native void throwError(C_GlueSchemaRegistryErrorPointerHolder pErr, CCharPointer msg, int code); +} diff --git a/native-schema-registry/target/ignore b/native-schema-registry/target/ignore new file mode 100644 index 00000000..69608201 --- /dev/null +++ b/native-schema-registry/target/ignore @@ -0,0 +1 @@ +Make sure target directory exists. diff --git a/pom.xml b/pom.xml index 13468566..28f7782a 100644 --- a/pom.xml +++ b/pom.xml @@ -69,6 +69,7 @@ kafkastreams-serde avro-kafkaconnect-converter avro-flink-serde + native-schema-registry examples integration-tests jsonschema-kafkaconnect-converter