Code Monkey home page Code Monkey logo

tigerbeetle-cpp's Introduction

TigerBeetle C++ client (Header only)

TigerBeetle is a financial accounting database designed for mission critical safety and performance to power the future of financial services.

Prerequisites

C++ version: 20

Libraries

  • fmtlib v10.1.1
  • TigerBeetle C client library (latest version - branch main)

Tools

  • cmake v3.14 or higher
  • zig v0.11.0 (tigerbeetle compatible)

How to Build and Run

Another C++ toolchain

$> cmake -B build # (tb_client.[a|lib])
# OR
$> cmake -B build -DTIGERBEETLE_BUILD_SHARED_LIBS=ON # (tb_client.[so|dll|dylib])
# Build and test - build client examples
$> cmake --build build -DBUILD_EXAMPLES=ON --target run_with_tb # run TigerBeetle server + your client 

Zig toolchain

# Linux/MacOS
$> cmake -B build -DCMAKE_CXX_COMPILER=scripts/zigcxx.sh
# Windows
$> cmake -B build -DCMAKE_CXX_COMPILER=scripts/zigcxx.cmd

How to use

  • Add on your cmake project:
include(FetchContent)

find_package(TigerBeetle 0.3.1 QUIET)
if (NOT TigerBeetle_FOUND)
    FetchContent_Declare(TigerBeetle GIT_REPOSITORY https://github.com/kassane/tigerbeetle-cpp.git
        GIT_TAG main)
    FetchContent_GetProperties(TigerBeetle)
# required
    set(APP_TARGETS ${PROJECT_NAME}) # executable or executables (need foreach) names
# optional
#   set(TB_VERSION 0.13.137) # tigerbeetle branch/tag repo (default: main)
#   set(TB_ADDRESS 3000) # tb_server port (default: 3001)
    FetchContent_MakeAvailable(TigerBeetle)
endif()

# linking your app to tb_client library
target_link_libraries(${PROJECT_NAME}
    PRIVATE tb_client
)
target_include_directories(${PROJECT_NAME} PUBLIC ${TigerBeetle_SOURCE_DIR}/include)
target_link_directories(${PROJECT_NAME} PUBLIC ${TigerBeetle_BINARY_DIR})

Build Samples

See:

Output
# possible output
[100%] Built target tb_cpp
Running tb_cpp with TigerBeetle
Starting replica 0

running client...
error(message_bus): error connecting to replica 0: error.ConnectionRefused
info(message_bus): connected to replica 0
TigerBeetle C++ Sample

[trace] Connecting...
[trace] Creating accounts...
[info] Accounts created successfully
[trace] Creating transfers...
[info] Transfers created successfully
============================================
[trace] 194 transfers per second
[trace] create_transfers max p100 latency per 8191 transfers = 1294686ms
[trace] total 819100 transfers in 4200636ms
[info] Looking up accounts ...
[info] 2 Account(s) found
============================================
[trace] id=1
[trace] debits_posted=819100
[trace] credits_posted=0
[trace] id=2
[trace] debits_posted=0
[trace] credits_posted=819100

Done!!
Killing tigerbeetle start process...
Terminating tigerbeetle start process...
[100%] Built target run_with_tb
Compiler Tested tb_client library
GCC πŸ†— Shared
GCC πŸ†— Static
Clang πŸ†— Shared
Clang πŸ†— Static
AppleClang πŸ†— Shared
AppleClang πŸ†— Static
zig cc/c++ πŸ†— Shared
zig cc/c++ πŸ†— Static
MSVC None Shared
MSVC None Static

Note: zig c++ equal to clang++ -stdlib=libc++ -fuse-ld=lld for all targets (builtin), except to MacOS target, replacing lld to zld!!

TODO

  • zig 0.11.0 - missing zig-pkg (choose cmake or zig only) to c_client support.

Frequently Asked Questions

Do I need to install Zig to compile this project?

A: No! You can use the C and/or C++ compiler of your choice.

However, as mentioned in issue #3, it will only be possible to link dynamically. The Zig static library does not include compiler-rt library, it only includes executables and shared libraries.

It is also not limited to C++, you just need to modify the CMakeLists.txt to use it with other languages supported by CMake.

ℹ️ CMake: Supported languages are C, CXX (i.e. C++), CSharp (i.e. C#), CUDA, OBJC (i.e. Objective-C), OBJCXX (i.e. Objective-C++), Fortran, HIP, ISPC, Swift, ASM, ASM_NASM, ASM_MARMASM, ASM_MASM, and ASM-ATT.

See: cmake docs

Is this project an official binding for TigerBeetleDB?

A: No! It's only a community project. But there's nothing stopping the main developers from porting it to the official repository if they want to.

What is the goal of tigerbeetle-cpp?

A: Firstly, to provide a simple C++ solution derived from the C binding (thanks to @batiati).

Also, to demonstrate that it's possible to use Zig with CMake to build the tb_client library without the user needing to use the Zig toolchain (C and/or C++). They don't even need to learn it if they don't want to. (I suggest reconsidering this matter!!)

Another important point is that TigerBeetle is a product in the early stages of development, subject to flaws and mistakes. The best way to improve this new tool is by testing, and that's where the relevance of the clients (language bindings) comes into play.

References

language binding description
C client-c Official
Elixir tigerbeetlex Community
Go client-go Official
Java client-java Official
.Net client-dotnet Official
Node client-node Official
Rust tigerbeetle-rs Community

License

See: LICENSE

tigerbeetle-cpp's People

Contributors

dependabot[bot] avatar kassane avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar

tigerbeetle-cpp's Issues

Case Study: C++ Thread-Safety Concurrency

Getting briefly talked about in the last PR.

The plan is to begin to investigate a case for implementing a solution for concurrency that is compatible with the API of the tb_client library.

Note: The latest commit, C++ version has been downgraded to 14. It is not necessary to have the latest version for a proposal.
However, nothing prohibits a better implementation!

#2 (comment)

I think C++ could follow the same strategy we have with Java/C# clients, exposing both async and blocking APIs.
An idiomatic C++ API could provide an async API by exposing a high-level callback/lambda, or even explore modern C++ async (is that a use case for promises?).

cc: @batiati @kprotty

Reference

`tb_client` linking error on MinGW

Reference:

cc: @batiati

Two events caused the error:

zig c++ error:
https://github.com/kassane/tigerbeetle-cpp/actions/runs/5489344878/jobs/10003387471#step:6:82

build log
lld-link: error: duplicate symbol: _alloca
>>> defined at tb_client.lib(compiler_rt.obj)
>>> defined at compiler_rt.lib(compiler_rt.lib.obj)

lld-link: error: duplicate symbol: ___chkstk_ms
>>> defined at tb_client.lib(compiler_rt.obj)
>>> defined at compiler_rt.lib(compiler_rt.lib.obj)

lld-link: error: duplicate symbol: .weak.__clzsi2.default._alloca
>>> defined at tb_client.lib(compiler_rt.obj)
>>> defined at compiler_rt.lib(compiler_rt.lib.obj)

lld-link: error: duplicate symbol: .weak.__clzdi2.default._alloca
>>> defined at tb_client.lib(compiler_rt.obj)
>>> defined at compiler_rt.lib(compiler_rt.lib.obj)

lld-link: error: duplicate symbol: .weak.__clzti2.default._alloca
>>> defined at tb_client.lib(compiler_rt.obj)
>>> defined at compiler_rt.lib(compiler_rt.lib.obj)

lld-link: error: duplicate symbol: .weak.__ctzsi2.default._alloca
>>> defined at tb_client.lib(compiler_rt.obj)
>>> defined at compiler_rt.lib(compiler_rt.lib.obj)

lld-link: error: duplicate symbol: .weak.__ctzdi2.default._alloca
>>> defined at tb_client.lib(compiler_rt.obj)
>>> defined at compiler_rt.lib(compiler_rt.lib.obj)

lld-link: error: duplicate symbol: .weak.__ctzti2.default._alloca
>>> defined at tb_client.lib(compiler_rt.obj)
>>> defined at compiler_rt.lib(compiler_rt.lib.obj)

lld-link: error: duplicate symbol: .weak.__ffssi2.default._alloca
>>> defined at tb_client.lib(compiler_rt.obj)
>>> defined at compiler_rt.lib(compiler_rt.lib.obj)

lld-link: error: duplicate symbol: .weak.__ffsdi2.default._alloca
>>> defined at tb_client.lib(compiler_rt.obj)
>>> defined at compiler_rt.lib(compiler_rt.lib.obj)

lld-link: error: duplicate symbol: .weak.__ffsti2.default._alloca
>>> defined at tb_client.lib(compiler_rt.obj)
>>> defined at compiler_rt.lib(compiler_rt.lib.obj)

lld-link: error: duplicate symbol: .weak.__paritysi2.default._alloca
>>> defined at tb_client.lib(compiler_rt.obj)
>>> defined at compiler_rt.lib(compiler_rt.lib.obj)

lld-link: error: duplicate symbol: .weak.__paritydi2.default._alloca
>>> defined at tb_client.lib(compiler_rt.obj)
>>> defined at compiler_rt.lib(compiler_rt.lib.obj)

lld-link: error: duplicate symbol: .weak.__parityti2.default._alloca
>>> defined at tb_client.lib(compiler_rt.obj)
>>> defined at compiler_rt.lib(compiler_rt.lib.obj)

lld-link: error: duplicate symbol: .weak.__popcountsi2.default._alloca
>>> defined at tb_client.lib(compiler_rt.obj)
>>> defined at compiler_rt.lib(compiler_rt.lib.obj)

lld-link: error: duplicate symbol: .weak.__popcountdi2.default._alloca
>>> defined at tb_client.lib(compiler_rt.obj)
>>> defined at compiler_rt.lib(compiler_rt.lib.obj)

lld-link: error: duplicate symbol: .weak.__popcountti2.default._alloca
>>> defined at tb_client.lib(compiler_rt.obj)
>>> defined at compiler_rt.lib(compiler_rt.lib.obj)

lld-link: error: duplicate symbol: .weak.__bswapsi2.default._alloca
>>> defined at tb_client.lib(compiler_rt.obj)
>>> defined at compiler_rt.lib(compiler_rt.lib.obj)
# [...] more info..

msys2/clang++ error:
https://github.com/kassane/tigerbeetle-cpp/actions/runs/5489463390/jobs/10003650798?pr=9#step:6:80

build log
ld.lld: error: undefined symbol: NtCreateKeyedEvent
>>> referenced by C:\_\build\_deps\tb-src\zig\lib\std\Thread\StaticResetEvent.zig:40
>>>               tb_client.lib(tb_client.obj):(std.Thread.StaticResetEvent.wait)

ld.lld: error: undefined symbol: NtWaitForKeyedEvent
>>> referenced by C:\_\build\_deps\tb-src\zig\lib\std\Thread\StaticResetEvent.zig:40
>>>               tb_client.lib(tb_client.obj):(std.Thread.StaticResetEvent.wait)
>>> referenced by C:\_\build\_deps\tb-src\zig\lib\std\Thread\StaticResetEvent.zig:40
>>>               tb_client.lib(tb_client.obj):(std.Thread.StaticResetEvent.wait)

ld.lld: error: undefined symbol: NtClose
>>> referenced by C:\_\build\_deps\tb-src\src\io\windows.zig:31
>>>               tb_client.lib(tb_client.obj):(io.windows.IO.deinit)
>>> referenced by C:\_\build\_deps\tb-src\zig\lib\std\debug.zig:608
>>>               tb_client.lib(tb_client.obj):(std.debug.printSourceAtAddress)
>>> referenced by C:\_\build\_deps\tb-src\zig\lib\std\debug.zig:608
>>>               tb_client.lib(tb_client.obj):(std.debug.printSourceAtAddress)
>>> referenced 11 more times



ld.lld: error: undefined symbol: NtCreateFile

>>> referenced by C:\_\build\_deps\tb-src\zig\lib\std\fs.zig:1070

>>>               tb_client.lib(tb_client.obj):(std.fs.Dir.openFileW)



ld.lld: error: undefined symbol: NtLockFile

>>> referenced by C:\_\build\_deps\tb-src\zig\lib\std\fs.zig:1089

>>>               tb_client.lib(tb_client.obj):(std.fs.Dir.openFileW)

c++: error: linker command failed with exit code 1 (use -v to see invocation)

Linux: ABI conflict

Transfers per second discrepancy.

Using another compiler: [g++/clang++] w/ libstdc++ & libgcc_s

TigerBeetle C++ - Basic [Sample]

[trace] Connecting...
[trace] Creating accounts...
info(message_bus): connected to replica 0
[info] Accounts created successfully
[trace] Creating transfers...
[info] Transfers created successfully
============================================
[trace] 0 transfers per second
[trace] create_transfers max p100 latency per 8191 transfers = 830487929ms
[trace] total 819100 transfers in 6513614745ms
[info] Looking up accounts ...
[info] 2 Account(s) found
============================================
[trace] id=1
[trace] debits_posted=819100
[trace] credits_posted=0
[trace] id=2
[trace] debits_posted=0
[trace] credits_posted=819100

Done!!

Using another compiler: clang++ w/ libc++ & libcompiler-rt

TigerBeetle C++ - Basic [Sample]

[trace] Connecting...
[trace] Creating accounts...
error(message_bus): error connecting to replica 0: error.ConnectionRefused
info(message_bus): connected to replica 0
[info] Accounts created successfully
[trace] Creating transfers...
[info] Transfers created successfully
============================================
[trace] 115 transfers per second
[trace] create_transfers max p100 latency per 8191 transfers = 779962ms
[trace] total 819100 transfers in 7090742ms
[info] Looking up accounts ...
[info] 2 Account(s) found
============================================
[trace] id=1
[trace] debits_posted=819100
[trace] credits_posted=0
[trace] id=2
[trace] debits_posted=0
[trace] credits_posted=819100

Done!!

Using zig c++ compiler (0.11.0 or master)

TigerBeetle C++ - Basic [Sample]

[trace] Connecting...
[trace] Creating accounts...
info(message_bus): connected to replica 0
[info] Accounts created successfully
[trace] Creating transfers...
[info] Transfers created successfully
============================================
[trace] 115 transfers per second
[trace] create_transfers max p100 latency per 8191 transfers = 764367ms
[trace] total 819100 transfers in 7063452ms
[info] Looking up accounts ...
[info] 2 Account(s) found
============================================
[trace] id=1
/home/kassane/Documentos/tigerbeetle-cpp/scripts/runner.sh, line 30: 22884 Segmentation failure (core image saved)$1
Error running with tigerbeetle
info(io): opening "0_0.tigerbeetle"...
info(main): 0: Allocated 5539MB in 15 regions during replica init (Grid Cache: 1024MB)
info(main): 0: cluster=0: listening on 127.0.0.1:3001
info(message_bus): connection from client 286812941245916550347703708496217723651
make[3]: *** [CMakeFiles/run_with_tb.dir/build.make:76: run_with_tb] Error 139
make[2]: *** [CMakeFiles/Makefile2:106: CMakeFiles/run_with_tb.dir/all] Error 2
make[1]: *** [CMakeFiles/Makefile2:113: CMakeFiles/run_with_tb.dir/rule] Error 2
make: *** [Makefile:169: run_with_tb] Error 2

C gcc

TigerBeetle C Sample
Connecting...
Creating accounts...
error(message_bus): error connecting to replica 0: error.ConnectionRefused
info(message_bus): connected to replica 0
Accounts created successfully
Creating transfers...
Transfers created successfully
============================================
133490 transfers per second
create_transfers max p100 latency per 8191 transfers = 743ms
total 819100 transfers in 6136ms

Looking up accounts ...
2 Account(s) found
============================================
id=1
debits_posted=819100
credits_posted=0

id=2
debits_posted=0
credits_posted=819100


Done!!

cc: @batiati


Rust high_level client (sample)

TigerBeetle Rust/C Sample
Connecting...
info(message_bus): connected to replica 0
Accounts created successfully
Creating transfers...
Transfers created successfully
============================================
61130 transfers per second
create_transfers max p100 latency per 8191 transfers = 1110ms
total 819100 transfers in 13399ms

Looking up accounts ...
2 Account(s) found
============================================
Account { id: 1, debits_posted: 819100, credits_posted: 0, .. }
Account { id: 2, debits_posted: 0, credits_posted: 819100, .. }

Done!!

ref.: zetanumbers/tigerbeetle-rs#9

Add more CI/CD build tests

Static & Shared tb_client library build

Linux

  • GCC
  • Clang

MacOS

  • AppleClang

Windows

  • MinGW GCC/Clang (msys2/ucrt64)
  • MinGW Clang - 9305d82
  • MSVC

Note: msys2/ucrt{32|64} or msys2/mingw{32|64} are libstdc++ (GNU C++ABI) and msys2/clang{64|32|arm64} are libcxx (LLVM C++ABI)

Crash: debug mode

https://github.com/kassane/tigerbeetle-cpp/actions/runs/6342186216/job/17227391172

 debug(client): 240807288813660370270376636803843266767: on_reply: user_data=1734443298969373479467440598314688 request=102 size=384 lookup_accounts
debug(vsr): 240807288813660370270376636803843266767: request_timeout stopped
thread 3396 panic: reached unreachable code
/home/runner/work/tigerbeetle-cpp/tigerbeetle-cpp/build/_deps/tb-src/zig/lib/std/debug.zig:343:14: 0x5583befbb5cc in assert (tb_client)
    if (!ok) unreachable; // assertion failure
             ^
/home/runner/work/tigerbeetle-cpp/tigerbeetle-cpp/build/_deps/tb-src/src/vsr/client.zig:154:19: 0x5583befccd7d in deinit (tb_client)
            assert(self.messages_available == constants.client_request_queue_max);
                  ^
/home/runner/work/tigerbeetle-cpp/tigerbeetle-cpp/build/_deps/tb-src/src/clients/c/tb_client/context.zig:202:35: 0x5583befd3b45 in deinit (tb_client)
                self.client.deinit(self.allocator);
                                  ^
/home/runner/work/tigerbeetle-cpp/tigerbeetle-cpp/build/_deps/tb-src/src/clients/c/tb_client/context.zig:351:27: 0x5583befccd27 in on_deinit (tb_client)
            context.deinit();
                          ^
/home/runner/work/tigerbeetle-cpp/tigerbeetle-cpp/build/_deps/tb-src/src/clients/c/tb_client.zig:222:24: 0x5583befbb52a in deinit (tb_client)
    (context.deinit_fn)(context);
                       ^
/home/runner/work/tigerbeetle-cpp/tigerbeetle-cpp/include/tb_client.hpp:107:23: 0x5583befb87c0 in destroy (/home/runner/work/tigerbeetle-cpp/tigerbeetle-cpp/examples/basic.cpp)
      tb_client_deinit(client);
                      ^
/home/runner/work/tigerbeetle-cpp/tigerbeetle-cpp/include/tb_client.hpp:79:22: 0x5583befb8645 in ~Client (/home/runner/work/tigerbeetle-cpp/tigerbeetle-cpp/examples/basic.cpp)
  ~Client() { destroy(); }
                     ^
/home/runner/work/tigerbeetle-cpp/tigerbeetle-cpp/examples/basic.cpp:238:1: 0x5583befb7595 in main (/home/runner/work/tigerbeetle-cpp/tigerbeetle-cpp/examples/basic.cpp)
}
^
Unwind error at address `:0x5583befb7595` (error.UnimplementedUserOpcode), trace may be incomplete

/home/runner/work/tigerbeetle-cpp/tigerbeetle-cpp/scripts/runner.sh: line 30:  3396 Aborted                 (core dumped) $1
Error running with tigerbeetle
info(io): opening "0_0.tigerbeetle"...
info(main): 0: Allocated 5539MB in 15 regions during replica init (Grid Cache: 1024MB)
gmake[3]: *** [CMakeFiles/run_with_tb.dir/build.make:76: run_with_tb] Error 134
info(main): 0: cluster=0: listening on 127.0.0.1:3001
gmake[2]: *** [CMakeFiles/Makefile2:106: CMakeFiles/run_with_tb.dir/all] Error 2
gmake[1]: *** [CMakeFiles/Makefile2:113: CMakeFiles/run_with_tb.dir/rule] Error 2
gmake: *** [Makefile:169: run_with_tb] Error 2
info(message_bus): connection from client 240807288813660370270376636803843266767
Error: Process completed with exit code 2.

References:

MacOS cannot run `basic` client sample [C++]

after #21 and tigerbeetle/tigerbeetle#1209 on MacOS persist error

Ref.: https://github.com/kassane/tigerbeetle-cpp/actions/runs/6472993099/job/17574753331

Starting replica 0

running client...
info(message_bus): connected to replica 0
/Users/runner/work/tigerbeetle-cpp/tigerbeetle-cpp/scripts/runner.sh: line 31:  3258 Segmentation fault: 11  $1
Error running with tigerbeetle
info(io): opening "0_0.tigerbeetle"...
info(main): 0: Allocated 5347MB in 16 regions during replica init (Grid Cache: 1024MB)
info(main): 0: cluster=0: listening on 127.0.0.1:3001
info(message_bus): connection from client 123649564302046689183064190193078852059
info(message_bus): peer performed an orderly shutdown: message_bus.MessageBusType(.replica).Connection.Peer{ .client = 123649564302046689183064190193078852059 }
make[3]: *** [run_with_tb] Error 139
make[2]: *** [CMakeFiles/run_with_tb.dir/all] Error 2
make[1]: *** [CMakeFiles/run_with_tb.dir/rule] Error 2
make: *** [run_with_tb] Error 2

cc: @batiati

Originally posted by @kassane in #16 (comment)

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    πŸ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. πŸ“ŠπŸ“ˆπŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❀️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.