I'm utilizing the ExternalWorkload to test custom layers within the FoundationDB simulation. The layers under test are authored in Rust and are based on the foundationdb-rs project. The workload API is defined by the C++ header file ClientWorkload.h. Interoperability between Rust and C++ presents challenges, although creating a C++ to C shim was relatively straightforward. My main concern is the unstable ABI of the C++ API, as it relies on the compiler, linker, and system libraries. This proved to be an issue when transitioning from version 7.1 to 7.3, where the workload I was using suddenly broke due to a change in the representation of the std::string class as the fdbserver switched from gcc to clang, as detailed in this forum thread and issue #11298.
To address this, I propose that alongside the existing C++ API (utilized by JavaWorkload), pure C bindings should be made available to ease integration with other languages and mitigate the impact of changes in compilation environments. This aligns well with the location of ClientWorkload.h in the bindings/c folder.
Given my limited familiarity with the FoundationDB codebase, I resorted to various wrappers to minimize code changes. However, a more efficient approach might involve rewriting the ExternalWorkload or creating a dedicated C version.
In this PR, I've divided ClientWorkload.h into CWorkload.h and CppWorkload.h. Importing CppWorkload.h should mirror the behavior of the original ClientWorkload.h, ensuring compatibility with existing workloads utilizing this API. The C bindings introduce BridgeToClient and BridgeToServer structs that encapsulate collections of function pointers. If the "useCAPI" option is enabled in the ExternalWorkload configuration file, it will load the workloadInstantiate symbol (instead of workloadFactory) and invoke it with the server-bridge (allowing the C workload to interact with the C++ FDBWorkloadContext and GenericPromise<bool> classes). The returned client-bridge is then encapsulated within a C++ "translator" workload and assigned as the workloadImpl of the ExternalWorkload.
I'm utilizing the
ExternalWorkload
to test custom layers within the FoundationDB simulation. The layers under test are authored in Rust and are based on the foundationdb-rs project. The workload API is defined by the C++ header fileClientWorkload.h
. Interoperability between Rust and C++ presents challenges, although creating a C++ to C shim was relatively straightforward. My main concern is the unstable ABI of the C++ API, as it relies on the compiler, linker, and system libraries. This proved to be an issue when transitioning from version 7.1 to 7.3, where the workload I was using suddenly broke due to a change in the representation of thestd::string
class as the fdbserver switched from gcc to clang, as detailed in this forum thread and issue #11298.To address this, I propose that alongside the existing C++ API (utilized by
JavaWorkload
), pure C bindings should be made available to ease integration with other languages and mitigate the impact of changes in compilation environments. This aligns well with the location ofClientWorkload.h
in thebindings/c
folder.Given my limited familiarity with the FoundationDB codebase, I resorted to various wrappers to minimize code changes. However, a more efficient approach might involve rewriting the
ExternalWorkload
or creating a dedicated C version.In this PR, I've divided
ClientWorkload.h
intoCWorkload.h
andCppWorkload.h
. ImportingCppWorkload.h
should mirror the behavior of the originalClientWorkload.h
, ensuring compatibility with existing workloads utilizing this API. The C bindings introduceBridgeToClient
andBridgeToServer
structs that encapsulate collections of function pointers. If the "useCAPI" option is enabled in theExternalWorkload
configuration file, it will load theworkloadInstantiate
symbol (instead ofworkloadFactory
) and invoke it with the server-bridge (allowing the C workload to interact with the C++FDBWorkloadContext
andGenericPromise<bool>
classes). The returned client-bridge is then encapsulated within a C++ "translator" workload and assigned as theworkloadImpl
of theExternalWorkload
.