Skip to content
Open
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
161 changes: 123 additions & 38 deletions zookeeper-client/zookeeper-client-c/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -23,24 +23,24 @@ set(description "zookeeper C client")
list(APPEND CMAKE_MODULE_PATH "${CMAKE_SOURCE_DIR}/../../tools/cmake/Modules")

# general options
if(UNIX)
add_compile_options(-Wall -fPIC)
elseif(WIN32)
if(MSVC)
add_compile_options(/W3)
elseif(MINGW)
add_compile_options(-Wall)
else()
add_compile_options(-Wall -fPIC)
endif()
add_definitions(-DUSE_STATIC_LIB)

option(BUILD_SHARED_LIBS "Build ZooKeeper client shared libraries" OFF)
option(BUILD_STATIC_LIBS "Also build ZooKeeper client static libraries" OFF)

# TODO: Enable /WX and /W4 on Windows. Currently there are ~1000 warnings.
# TODO: Add Solaris support.
# TODO: Add a shared library option.
# TODO: Specify symbols to export.
# TODO: Generate doxygen documentation.

# Sync API option
option(WANT_SYNCAPI "Enables Sync API support" ON)
if(WANT_SYNCAPI)
add_definitions(-DTHREADED)
endif()

# CppUnit option
if(WIN32 OR APPLE)
Expand Down Expand Up @@ -130,6 +130,11 @@ endforeach()

# function checks
include(CheckFunctionExists)
set(ZOOKEEPER_SAVED_REQUIRED_LIBRARIES ${CMAKE_REQUIRED_LIBRARIES})
if(WIN32)
# Winsock functions cannot be detected unless the probe links ws2_32.
list(APPEND CMAKE_REQUIRED_LIBRARIES ws2_32)
endif()
set(check_functions
getcwd
gethostbyname
Expand All @@ -147,10 +152,20 @@ set(check_functions
strerror
strtol)

# CheckFunctionExists cannot detect 32-bit stdcall Winsock symbols because it
# does not include their declarations, so record the known Windows APIs.
if(WIN32)
set(HAVE_GETHOSTBYNAME 1)
set(HAVE_GETHOSTNAME 1)
set(HAVE_SOCKET 1)
endif()

foreach(fn ${check_functions})
to_have(${fn} name)
check_function_exists(${fn} ${name})
endforeach()
set(CMAKE_REQUIRED_LIBRARIES ${ZOOKEEPER_SAVED_REQUIRED_LIBRARIES})
unset(ZOOKEEPER_SAVED_REQUIRED_LIBRARIES)

# library checks
set(check_libraries rt m pthread)
Expand All @@ -161,7 +176,13 @@ endforeach()

# IPv6 check
include(CheckStructHasMember)
check_struct_has_member("struct sockaddr_in6" sin6_addr "netinet/in.h" ZOO_IPV6_ENABLED)
if(WIN32)
check_struct_has_member("struct sockaddr_in6" sin6_addr
"winsock2.h;ws2tcpip.h" ZOO_IPV6_ENABLED)
else()
check_struct_has_member("struct sockaddr_in6" sin6_addr
"netinet/in.h" ZOO_IPV6_ENABLED)
endif()

# configure
configure_file(cmake_config.h.in ${CMAKE_CURRENT_BINARY_DIR}/include/config.h)
Expand All @@ -172,46 +193,81 @@ add_library(hashtable STATIC ${hashtable_sources})
target_include_directories(hashtable PUBLIC include)
target_link_libraries(hashtable PUBLIC $<$<OR:$<PLATFORM_ID:Linux>,$<PLATFORM_ID:FreeBSD>>:m>)

# zookeeper library
set(zookeeper_sources
# ZooKeeper client libraries
set(zookeeper_common_sources
src/zookeeper.c
src/recordio.c
generated/zookeeper.jute.c
src/zk_log.c
src/zk_hashtable.c
src/addrvec.c)

if(WANT_SYNCAPI)
list(APPEND zookeeper_sources src/mt_adaptor.c)
else()
list(APPEND zookeeper_sources src/st_adaptor.c)
endif()

if(CYRUS_SASL_FOUND)
list(APPEND zookeeper_sources src/zk_sasl.c)
list(APPEND zookeeper_common_sources src/zk_sasl.c)
endif()

if(WIN32)
list(APPEND zookeeper_sources src/winport.c)
list(APPEND zookeeper_common_sources src/winport.c)
endif()

add_library(zookeeper STATIC ${zookeeper_sources})
target_include_directories(zookeeper PUBLIC include ${CMAKE_CURRENT_BINARY_DIR}/include generated)
target_link_libraries(zookeeper PUBLIC
hashtable
$<$<PLATFORM_ID:Linux>:rt> # clock_gettime
$<$<PLATFORM_ID:Windows>:ws2_32>) # Winsock 2.0
function(add_zookeeper_library target variant library_type adaptor)
add_library(${target} ${library_type}
${zookeeper_common_sources} ${adaptor})
target_include_directories(${target} PUBLIC
include ${CMAKE_CURRENT_BINARY_DIR}/include generated)
target_link_libraries(${target} PUBLIC
hashtable
$<$<PLATFORM_ID:Linux>:rt> # clock_gettime
$<$<PLATFORM_ID:Windows>:ws2_32>) # Winsock 2.0
set_target_properties(${target} PROPERTIES OUTPUT_NAME zookeeper_${variant})

if("${library_type}" STREQUAL "SHARED")
if(WIN32)
# ZOOAPI expands to dllexport while compiling the DLL and dllimport for
# consumers. Export the remaining public generated/Jute entry points too.
target_compile_definitions(${target} PRIVATE DLL_EXPORT)
set_target_properties(${target} PROPERTIES WINDOWS_EXPORT_ALL_SYMBOLS ON)
endif()
else()
target_compile_definitions(${target} PUBLIC USE_STATIC_LIB)
endif()

if("${variant}" STREQUAL "mt")
target_compile_definitions(${target} PUBLIC THREADED)
endif()

set(zookeeper_library_targets ${zookeeper_library_targets} ${target} PARENT_SCOPE)
endfunction()

# Keep the historical CMake default (static only). Turning on both options
# produces static and shared artifacts in one build tree.
set(zookeeper_library_targets)
if(BUILD_SHARED_LIBS)
add_zookeeper_library(zookeeper_st_shared st SHARED src/st_adaptor.c)
if(WANT_SYNCAPI)
add_zookeeper_library(zookeeper_mt_shared mt SHARED src/mt_adaptor.c)
endif()
endif()

if(NOT BUILD_SHARED_LIBS OR BUILD_STATIC_LIBS)
add_zookeeper_library(zookeeper_st_static st STATIC src/st_adaptor.c)
if(WANT_SYNCAPI)
add_zookeeper_library(zookeeper_mt_static mt STATIC src/mt_adaptor.c)
endif()
endif()

option(WITH_OPENSSL "turn ON/OFF SSL support, or define openssl library location (default: ON)" ON)
message("-- using WITH_OPENSSL=${WITH_OPENSSL}")
if(NOT WITH_OPENSSL STREQUAL "OFF")
if(NOT WITH_OPENSSL STREQUAL "ON")
set(OPENSSL_ROOT_DIR,${WITH_OPENSSL})
set(OPENSSL_ROOT_DIR ${WITH_OPENSSL})
endif()
find_package(OpenSSL)
if(OPENSSL_FOUND)
target_compile_definitions(zookeeper PUBLIC HAVE_OPENSSL_H)
target_link_libraries(zookeeper PUBLIC OpenSSL::SSL OpenSSL::Crypto)
foreach(target ${zookeeper_library_targets})
target_compile_definitions(${target} PUBLIC HAVE_OPENSSL_H)
target_link_libraries(${target} PUBLIC OpenSSL::SSL OpenSSL::Crypto)
endforeach()
message("-- OpenSSL libraries found! will build with SSL support.")
else()
message("-- WARNING: unable to find OpenSSL libraries! will build without SSL support.")
Expand All @@ -220,22 +276,47 @@ endif()

if(WANT_SYNCAPI AND NOT WIN32)
find_package(Threads REQUIRED)
target_link_libraries(zookeeper PUBLIC Threads::Threads)
foreach(target zookeeper_mt_shared zookeeper_mt_static)
if(TARGET ${target})
target_link_libraries(${target} PUBLIC Threads::Threads)
endif()
endforeach()
endif()

if(CYRUS_SASL_FOUND)
target_compile_definitions(zookeeper PUBLIC HAVE_CYRUS_SASL_H)
target_link_libraries(zookeeper PUBLIC CyrusSASL)
foreach(target ${zookeeper_library_targets})
target_compile_definitions(${target} PUBLIC HAVE_CYRUS_SASL_H)
target_link_libraries(${target} PUBLIC CyrusSASL)
endforeach()
endif()

# cli executable
add_executable(cli src/cli.c)
target_link_libraries(cli zookeeper)
# Command-line clients follow the Autotools layout. When both library kinds
# are requested, link the samples against the shared libraries.
if(TARGET zookeeper_st_shared)
set(zookeeper_st_cli_target zookeeper_st_shared)
else()
set(zookeeper_st_cli_target zookeeper_st_static)
endif()
add_executable(cli_st src/cli.c)
target_link_libraries(cli_st ${zookeeper_st_cli_target})

# Multithreaded client and load generator are only available with Sync API.
if(WANT_SYNCAPI)
if(TARGET zookeeper_mt_shared)
set(zookeeper_mt_cli_target zookeeper_mt_shared)
else()
set(zookeeper_mt_cli_target zookeeper_mt_static)
endif()
add_executable(cli_mt src/cli.c)
target_link_libraries(cli_mt ${zookeeper_mt_cli_target})

# load_gen executable
if(WANT_SYNCAPI AND NOT WIN32)
add_executable(load_gen src/load_gen.c)
target_link_libraries(load_gen zookeeper)
target_link_libraries(load_gen ${zookeeper_mt_cli_target})
if(WIN32)
# winport is an internal part of the client DLL, while load_gen uses its
# pthread compatibility helpers directly.
target_sources(load_gen PRIVATE src/winport.c)
endif()
endif()

# tests
Expand Down Expand Up @@ -273,7 +354,11 @@ if(WANT_CPPUNIT)
target_compile_definitions(zktest
PRIVATE -DZKSERVER_CMD="${CMAKE_CURRENT_SOURCE_DIR}/tests/zkServer.sh")
# TODO: Use `find_library()` for `cppunit`.
target_link_libraries(zktest zookeeper cppunit dl)
if(WANT_SYNCAPI)
target_link_libraries(zktest ${zookeeper_mt_cli_target} cppunit dl)
else()
target_link_libraries(zktest ${zookeeper_st_cli_target} cppunit dl)
endif()

# This reads the link flags from the file `tests/wrappers.opt` into
# the variable `symbol_wrappers` for use in `target_link_libraries`.
Expand Down
23 changes: 23 additions & 0 deletions zookeeper-client/zookeeper-client-c/README
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,29 @@ Please refer to the "Installation" item under "C Binding" in the
Programmer's Guide:
https://zookeeper.apache.org/doc/current/developer/programmers-guide/bindings#installation

MINGW-W64

The CMake build supports both 32-bit and 64-bit MinGW-w64 toolchains. Before
configuring, run `mvn -pl zookeeper-jute generate-sources -DskipTests` from the
ZooKeeper top-level directory to generate the Jute C sources. A typical 64-bit
cross-build from Linux is:

cmake -S . -B build-mingw64 \
-DCMAKE_SYSTEM_NAME=Windows \
-DCMAKE_C_COMPILER=x86_64-w64-mingw32-gcc \
-DCMAKE_CXX_COMPILER=x86_64-w64-mingw32-g++ \
-DBUILD_SHARED_LIBS=ON \
-DWITH_OPENSSL=OFF -DWITH_CYRUS_SASL=OFF
cmake --build build-mingw64

Use i686-w64-mingw32-gcc and i686-w64-mingw32-g++ for a 32-bit build. OpenSSL
and Cyrus SASL can be enabled when MinGW-built versions of those dependencies
are available to CMake. CMake always builds the single-threaded zookeeper_st
library and, unless `-DWANT_SYNCAPI=OFF` is used, also builds the multithreaded
zookeeper_mt library. Set `-DBUILD_STATIC_LIBS=ON` alongside
`-DBUILD_SHARED_LIBS=ON` to produce both static and shared libraries in one
build directory.

EXAMPLE/SAMPLE C CLIENT SHELL

NOTE: the ZooKeeper C client shell (cli_st and cli_mt) is meant as a
Expand Down
5 changes: 4 additions & 1 deletion zookeeper-client/zookeeper-client-c/include/win_getopt.h
Original file line number Diff line number Diff line change
Expand Up @@ -77,7 +77,9 @@

#ifndef __GETOPT_H__

#pragma warning(disable:4996);
#ifdef _MSC_VER
#pragma warning(disable:4996)
#endif

#define __GETOPT_H__

Expand Down Expand Up @@ -136,6 +138,7 @@ static char EMSG[] = "";
#define EMSG ""
#endif

struct option;
static int getopt_internal(int, char * const *, const char *,
const struct option *, int *, int);
static int parse_long_options(char * const *, const char *,
Expand Down
6 changes: 3 additions & 3 deletions zookeeper-client/zookeeper-client-c/include/winconfig.h
Original file line number Diff line number Diff line change
@@ -1,14 +1,14 @@
#ifndef WINCONFIG_H_
#define WINCONFIG_H_

/* Define to `__inline__' or `__inline' if that's what the C compiler
calls it, or to nothing if 'inline' is not supported under any name. */
/* GCC-compatible attributes and C99 keywords are supported by MinGW. */
#ifdef _MSC_VER
#ifndef __cplusplus
#define inline __inline
#endif

#define __attribute__(x)
#define __func__ __FUNCTION__
#endif

#define ACL ZKACL /* Conflict with windows API */

Expand Down
3 changes: 1 addition & 2 deletions zookeeper-client/zookeeper-client-c/src/addrvec.h
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@
#include <netinet/in.h>
#include <netdb.h>
#else
#include <WinSock2.h>
#include <winsock2.h>
#include <stdint.h>
#endif

Expand Down Expand Up @@ -135,4 +135,3 @@ int addrvec_eq(const addrvec_t *a1, const addrvec_t *a2);
#endif // ADDRVEC_H



8 changes: 8 additions & 0 deletions zookeeper-client/zookeeper-client-c/src/cli.c
Original file line number Diff line number Diff line change
Expand Up @@ -1054,13 +1054,21 @@ int main(int argc, char **argv) {
FD_ZERO(&wfds);
FD_ZERO(&efds);
while (!shutdownThisThing) {
#ifdef WIN32
SOCKET fd;
#else
int fd;
#endif
int interest;
int events;
struct timeval tv;
int rc;
zookeeper_interest(zh, &fd, &interest, &tv);
#ifdef WIN32
if (fd != INVALID_SOCKET) {
#else
if (fd != -1) {
#endif
if (interest&ZOOKEEPER_READ) {
FD_SET(fd, &rfds);
} else {
Expand Down
18 changes: 13 additions & 5 deletions zookeeper-client/zookeeper-client-c/src/load_gen.c
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,9 @@
#include <zookeeper.h>
#include "zookeeper_log.h"
#include <errno.h>
#ifdef THREADED
#ifdef WIN32
#include "winport.h"
#else
#include <pthread.h>
#endif
#include <string.h>
Expand All @@ -29,11 +31,11 @@ static zhandle_t *zh;

// *****************************************************************************
//
static pthread_cond_t cond=PTHREAD_COND_INITIALIZER;
static pthread_mutex_t lock=PTHREAD_MUTEX_INITIALIZER;
static pthread_cond_t cond;
static pthread_mutex_t lock;

static pthread_cond_t counterCond=PTHREAD_COND_INITIALIZER;
static pthread_mutex_t counterLock=PTHREAD_MUTEX_INITIALIZER;
static pthread_cond_t counterCond;
static pthread_mutex_t counterLock;
static int counter;


Expand Down Expand Up @@ -230,6 +232,12 @@ void usage(char *argv[]){
int main(int argc, char **argv) {
int nodeCount;
int cleaning=0;

pthread_mutex_init(&lock, 0);
pthread_cond_init(&cond, 0);
pthread_mutex_init(&counterLock, 0);
pthread_cond_init(&counterCond, 0);

if (argc < 4) {
usage(argv);
}
Expand Down
Loading
Loading