/* * fdb_c.h * * This source file is part of the FoundationDB open source project * * Copyright 2013-2022 Apple Inc. and the FoundationDB project authors * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #ifndef FDB_C_H #define FDB_C_H #pragma once #ifndef DLLEXPORT #define DLLEXPORT #endif #if !defined(FDB_API_VERSION) #error You must #define FDB_API_VERSION prior to including fdb_c.h (current version is 710) #elif FDB_API_VERSION < 13 #error API version no longer supported (upgrade to 13) #elif FDB_API_VERSION > 710 #error Requested API version requires a newer version of this header #endif #if FDB_API_VERSION >= 23 && !defined(WARN_UNUSED_RESULT) #ifdef __GNUG__ #define WARN_UNUSED_RESULT __attribute__((warn_unused_result)) #else #define WARN_UNUSED_RESULT #endif #else #define WARN_UNUSED_RESULT #endif /* * With default settings, gcc will not warn about unprototyped functions being * called, so it is easy to erroneously call a function which is not available * at FDB_API_VERSION and then get an error only at runtime. These macros * ensure a compile error in such cases, and attempt to make the compile error * slightly informative. */ #define This_FoundationDB_API_function_is_removed_at_this_FDB_API_VERSION() \ { == == = } #define FDB_REMOVED_FUNCTION This_FoundationDB_API_function_is_removed_at_this_FDB_API_VERSION(0) #include #include "fdb_c_options.g.h" #include "fdb_c_types.h" #ifdef __cplusplus extern "C" { #endif DLLEXPORT const char* fdb_get_error(fdb_error_t code); DLLEXPORT fdb_bool_t fdb_error_predicate(int predicate_test, fdb_error_t code); #define /* fdb_error_t */ fdb_select_api_version(v) fdb_select_api_version_impl(v, FDB_API_VERSION) DLLEXPORT WARN_UNUSED_RESULT fdb_error_t fdb_network_set_option(FDBNetworkOption option, uint8_t const* value, int value_length); #if FDB_API_VERSION >= 14 DLLEXPORT WARN_UNUSED_RESULT fdb_error_t fdb_setup_network(); #endif DLLEXPORT WARN_UNUSED_RESULT fdb_error_t fdb_run_network(); DLLEXPORT WARN_UNUSED_RESULT fdb_error_t fdb_stop_network(); DLLEXPORT WARN_UNUSED_RESULT fdb_error_t fdb_add_network_thread_completion_hook(void (*hook)(void*), void* hook_parameter); #pragma pack(push, 4) typedef struct key { const uint8_t* key; int key_length; } FDBKey; #if FDB_API_VERSION >= 710 typedef struct keyvalue { const uint8_t* key; int key_length; const uint8_t* value; int value_length; } FDBKeyValue; #else typedef struct keyvalue { const void* key; int key_length; const void* value; int value_length; } FDBKeyValue; #endif #pragma pack(pop) /* Memory layout of KeySelectorRef. */ typedef struct keyselector { FDBKey key; /* orEqual and offset have not be tested in C binding. Just a placeholder. */ fdb_bool_t orEqual; int offset; } FDBKeySelector; /* Memory layout of GetRangeReqAndResultRef. */ typedef struct getrangereqandresult { FDBKeySelector begin; FDBKeySelector end; FDBKeyValue* data; int m_size, m_capacity; } FDBGetRangeReqAndResult; /* Memory layout of MappedKeyValueRef. Total 112 bytes - key (12 bytes) :74:8F:8E:5F:AE:7F:00:00 :4A:00:00:00 - value (12 bytes) :70:8F:8E:5F:AE:7F:00:00 :00:00:00:00 - begin selector (20 bytes) :30:8F:8E:5F:AE:7F:00:00 :2D:00:00:00 :00:7F:00:00 :01:00:00:00 - end selector (20 bytes) :EC:8E:8E:5F:AE:7F:00:00 :2D:00:00:00 :00:2B:3C:60 :01:00:00:00 - vector (16 bytes) :74:94:8E:5F:AE:7F:00:00 :01:00:00:00 :01:00:00:00 - buffer (32 bytes) :00:20:D1:61:00:00:00:00 :00:00:00:00:00:00:00:00 :00:00:00:00:00:00:00:00 :01:00:00:00:AE:7F:00:00 */ typedef struct mappedkeyvalue { FDBKey key; FDBKey value; /* It's complicated to map a std::variant to C. For now we assume the underlying requests are always getRange and * take the shortcut. */ FDBGetRangeReqAndResult getRange; unsigned char buffer[32]; } FDBMappedKeyValue; #pragma pack(push, 4) typedef struct keyrange { const uint8_t* begin_key; int begin_key_length; const uint8_t* end_key; int end_key_length; } FDBKeyRange; #pragma pack(pop) typedef struct readgranulecontext { /* User context to pass along to functions */ void* userContext; /* Returns a unique id for the load. Asynchronous to support queueing multiple in parallel. */ int64_t (*start_load_f)(const char* filename, int filenameLength, int64_t offset, int64_t length, int64_t fullFileLength, void* context); /* Returns data for the load. Pass the loadId returned by start_load_f */ uint8_t* (*get_load_f)(int64_t loadId, void* context); /* Frees data from load. Pass the loadId returned by start_load_f */ void (*free_load_f)(int64_t loadId, void* context); /* Set this to true for testing if you don't want to read the granule files, just do the request to the blob workers */ fdb_bool_t debugNoMaterialize; /* Number of granules to load in parallel */ int granuleParallelism; } FDBReadBlobGranuleContext; DLLEXPORT void fdb_future_cancel(FDBFuture* f); DLLEXPORT void fdb_future_release_memory(FDBFuture* f); DLLEXPORT void fdb_future_destroy(FDBFuture* f); DLLEXPORT WARN_UNUSED_RESULT fdb_error_t fdb_future_block_until_ready(FDBFuture* f); DLLEXPORT fdb_bool_t fdb_future_is_ready(FDBFuture* f); typedef void (*FDBCallback)(FDBFuture* future, void* callback_parameter); DLLEXPORT WARN_UNUSED_RESULT fdb_error_t fdb_future_set_callback(FDBFuture* f, FDBCallback callback, void* callback_parameter); #if FDB_API_VERSION >= 23 DLLEXPORT WARN_UNUSED_RESULT fdb_error_t fdb_future_get_error(FDBFuture* f); #endif DLLEXPORT WARN_UNUSED_RESULT fdb_error_t fdb_future_get_int64(FDBFuture* f, int64_t* out); DLLEXPORT WARN_UNUSED_RESULT fdb_error_t fdb_future_get_uint64(FDBFuture* f, uint64_t* out); DLLEXPORT WARN_UNUSED_RESULT fdb_error_t fdb_future_get_key(FDBFuture* f, uint8_t const** out_key, int* out_key_length); DLLEXPORT WARN_UNUSED_RESULT fdb_error_t fdb_future_get_value(FDBFuture* f, fdb_bool_t* out_present, uint8_t const** out_value, int* out_value_length); #if FDB_API_VERSION >= 14 DLLEXPORT WARN_UNUSED_RESULT fdb_error_t fdb_future_get_keyvalue_array(FDBFuture* f, FDBKeyValue const** out_kv, int* out_count, fdb_bool_t* out_more); #endif DLLEXPORT WARN_UNUSED_RESULT fdb_error_t fdb_future_get_mappedkeyvalue_array(FDBFuture* f, FDBMappedKeyValue const** out_kv, int* out_count, fdb_bool_t* out_more); DLLEXPORT WARN_UNUSED_RESULT fdb_error_t fdb_future_get_key_array(FDBFuture* f, FDBKey const** out_key_array, int* out_count); DLLEXPORT WARN_UNUSED_RESULT fdb_error_t fdb_future_get_string_array(FDBFuture* f, const char*** out_strings, int* out_count); DLLEXPORT WARN_UNUSED_RESULT fdb_error_t fdb_future_get_keyrange_array(FDBFuture* f, FDBKeyRange const** out_ranges, int* out_count); /* FDBResult is a synchronous computation result, as opposed to a future that is asynchronous. */ DLLEXPORT void fdb_result_destroy(FDBResult* r); DLLEXPORT WARN_UNUSED_RESULT fdb_error_t fdb_result_get_keyvalue_array(FDBResult* r, FDBKeyValue const** out_kv, int* out_count, fdb_bool_t* out_more); /* TODO: add other return types as we need them */ DLLEXPORT WARN_UNUSED_RESULT fdb_error_t fdb_create_database(const char* cluster_file_path, FDBDatabase** out_database); DLLEXPORT void fdb_database_destroy(FDBDatabase* d); DLLEXPORT WARN_UNUSED_RESULT fdb_error_t fdb_database_set_option(FDBDatabase* d, FDBDatabaseOption option, uint8_t const* value, int value_length); DLLEXPORT WARN_UNUSED_RESULT fdb_error_t fdb_database_open_tenant(FDBDatabase* d, uint8_t const* tenant_name, int tenant_name_length, FDBTenant** out_tenant); DLLEXPORT WARN_UNUSED_RESULT fdb_error_t fdb_database_create_transaction(FDBDatabase* d, FDBTransaction** out_transaction); DLLEXPORT WARN_UNUSED_RESULT FDBFuture* fdb_database_reboot_worker(FDBDatabase* db, uint8_t const* address, int address_length, fdb_bool_t check, int duration); DLLEXPORT WARN_UNUSED_RESULT FDBFuture* fdb_database_force_recovery_with_data_loss(FDBDatabase* db, uint8_t const* dcid, int dcid_length); DLLEXPORT WARN_UNUSED_RESULT FDBFuture* fdb_database_create_snapshot(FDBDatabase* db, uint8_t const* uid, int uid_length, uint8_t const* snap_command, int snap_command_length); DLLEXPORT WARN_UNUSED_RESULT double fdb_database_get_main_thread_busyness(FDBDatabase* db); DLLEXPORT WARN_UNUSED_RESULT FDBFuture* fdb_database_get_server_protocol(FDBDatabase* db, uint64_t expected_version); DLLEXPORT WARN_UNUSED_RESULT FDBFuture* fdb_database_purge_blob_granules(FDBDatabase* db, uint8_t const* begin_key_name, int begin_key_name_length, uint8_t const* end_key_name, int end_key_name_length, int64_t purge_version, fdb_bool_t force); DLLEXPORT WARN_UNUSED_RESULT FDBFuture* fdb_database_wait_purge_granules_complete(FDBDatabase* db, uint8_t const* purge_key_name, int purge_key_name_length); DLLEXPORT WARN_UNUSED_RESULT fdb_error_t fdb_tenant_create_transaction(FDBTenant* tenant, FDBTransaction** out_transaction); DLLEXPORT void fdb_tenant_destroy(FDBTenant* tenant); DLLEXPORT void fdb_transaction_destroy(FDBTransaction* tr); DLLEXPORT void fdb_transaction_cancel(FDBTransaction* tr); #if FDB_API_VERSION >= 14 DLLEXPORT WARN_UNUSED_RESULT fdb_error_t fdb_transaction_set_option(FDBTransaction* tr, FDBTransactionOption option, uint8_t const* value, int value_length); #endif DLLEXPORT void fdb_transaction_set_read_version(FDBTransaction* tr, int64_t version); DLLEXPORT WARN_UNUSED_RESULT FDBFuture* fdb_transaction_get_read_version(FDBTransaction* tr); #if FDB_API_VERSION >= 14 DLLEXPORT WARN_UNUSED_RESULT FDBFuture* fdb_transaction_get(FDBTransaction* tr, uint8_t const* key_name, int key_name_length, fdb_bool_t snapshot); #endif #if FDB_API_VERSION >= 14 DLLEXPORT WARN_UNUSED_RESULT FDBFuture* fdb_transaction_get_key(FDBTransaction* tr, uint8_t const* key_name, int key_name_length, fdb_bool_t or_equal, int offset, fdb_bool_t snapshot); #endif DLLEXPORT WARN_UNUSED_RESULT FDBFuture* fdb_transaction_get_addresses_for_key(FDBTransaction* tr, uint8_t const* key_name, int key_name_length); #if FDB_API_VERSION >= 14 DLLEXPORT WARN_UNUSED_RESULT FDBFuture* fdb_transaction_get_range(FDBTransaction* tr, uint8_t const* begin_key_name, int begin_key_name_length, fdb_bool_t begin_or_equal, int begin_offset, uint8_t const* end_key_name, int end_key_name_length, fdb_bool_t end_or_equal, int end_offset, int limit, int target_bytes, FDBStreamingMode mode, int iteration, fdb_bool_t snapshot, fdb_bool_t reverse); #endif DLLEXPORT WARN_UNUSED_RESULT FDBFuture* fdb_transaction_get_mapped_range(FDBTransaction* tr, uint8_t const* begin_key_name, int begin_key_name_length, fdb_bool_t begin_or_equal, int begin_offset, uint8_t const* end_key_name, int end_key_name_length, fdb_bool_t end_or_equal, int end_offset, uint8_t const* mapper_name, int mapper_name_length, int limit, int target_bytes, FDBStreamingMode mode, int iteration, fdb_bool_t snapshot, fdb_bool_t reverse); DLLEXPORT void fdb_transaction_set(FDBTransaction* tr, uint8_t const* key_name, int key_name_length, uint8_t const* value, int value_length); DLLEXPORT void fdb_transaction_atomic_op(FDBTransaction* tr, uint8_t const* key_name, int key_name_length, uint8_t const* param, int param_length, FDBMutationType operation_type); DLLEXPORT void fdb_transaction_clear(FDBTransaction* tr, uint8_t const* key_name, int key_name_length); DLLEXPORT void fdb_transaction_clear_range(FDBTransaction* tr, uint8_t const* begin_key_name, int begin_key_name_length, uint8_t const* end_key_name, int end_key_name_length); DLLEXPORT WARN_UNUSED_RESULT FDBFuture* fdb_transaction_watch(FDBTransaction* tr, uint8_t const* key_name, int key_name_length); DLLEXPORT WARN_UNUSED_RESULT FDBFuture* fdb_transaction_commit(FDBTransaction* tr); DLLEXPORT WARN_UNUSED_RESULT fdb_error_t fdb_transaction_get_committed_version(FDBTransaction* tr, int64_t* out_version); /* * This function intentionally returns an FDBFuture instead of an integer * directly, so that calling this API can see the effect of previous * mutations on the transaction. Specifically, mutations are applied * asynchronously by the main thread. In order to see them, this call has to * be serviced by the main thread too. */ DLLEXPORT WARN_UNUSED_RESULT FDBFuture* fdb_transaction_get_approximate_size(FDBTransaction* tr); DLLEXPORT WARN_UNUSED_RESULT FDBFuture* fdb_transaction_get_versionstamp(FDBTransaction* tr); DLLEXPORT WARN_UNUSED_RESULT FDBFuture* fdb_transaction_on_error(FDBTransaction* tr, fdb_error_t error); DLLEXPORT void fdb_transaction_reset(FDBTransaction* tr); DLLEXPORT WARN_UNUSED_RESULT fdb_error_t fdb_transaction_add_conflict_range(FDBTransaction* tr, uint8_t const* begin_key_name, int begin_key_name_length, uint8_t const* end_key_name, int end_key_name_length, FDBConflictRangeType type); DLLEXPORT WARN_UNUSED_RESULT FDBFuture* fdb_transaction_get_estimated_range_size_bytes(FDBTransaction* tr, uint8_t const* begin_key_name, int begin_key_name_length, uint8_t const* end_key_name, int end_key_name_length); DLLEXPORT WARN_UNUSED_RESULT FDBFuture* fdb_transaction_get_range_split_points(FDBTransaction* tr, uint8_t const* begin_key_name, int begin_key_name_length, uint8_t const* end_key_name, int end_key_name_length, int64_t chunk_size); DLLEXPORT WARN_UNUSED_RESULT FDBFuture* fdb_transaction_get_blob_granule_ranges(FDBTransaction* tr, uint8_t const* begin_key_name, int begin_key_name_length, uint8_t const* end_key_name, int end_key_name_length); /* LatestVersion (-2) for readVersion means get read version from transaction Separated out as optional because BG reads can support longer-lived reads than normal FDB transactions */ DLLEXPORT WARN_UNUSED_RESULT FDBResult* fdb_transaction_read_blob_granules(FDBTransaction* tr, uint8_t const* begin_key_name, int begin_key_name_length, uint8_t const* end_key_name, int end_key_name_length, int64_t beginVersion, int64_t readVersion, FDBReadBlobGranuleContext granuleContext); #define FDB_KEYSEL_LAST_LESS_THAN(k, l) k, l, 0, 0 #define FDB_KEYSEL_LAST_LESS_OR_EQUAL(k, l) k, l, 1, 0 #define FDB_KEYSEL_FIRST_GREATER_THAN(k, l) k, l, 1, 1 #define FDB_KEYSEL_FIRST_GREATER_OR_EQUAL(k, l) k, l, 0, 1 DLLEXPORT WARN_UNUSED_RESULT fdb_error_t fdb_select_api_version_impl(int runtime_version, int header_version); DLLEXPORT int fdb_get_max_api_version(); DLLEXPORT const char* fdb_get_client_version(); /* LEGACY API VERSIONS */ #if FDB_API_VERSION < 620 DLLEXPORT WARN_UNUSED_RESULT fdb_error_t fdb_future_get_version(FDBFuture* f, int64_t* out_version); #else #define fdb_future_get_version(f, ov) FDB_REMOVED_FUNCTION #endif #if FDB_API_VERSION < 610 || defined FDB_INCLUDE_LEGACY_TYPES typedef struct FDB_cluster FDBCluster; typedef enum { /* This option is only a placeholder for C compatibility and should not be used */ FDB_CLUSTER_OPTION_DUMMY_DO_NOT_USE = -1 } FDBClusterOption; #endif #if FDB_API_VERSION < 610 DLLEXPORT WARN_UNUSED_RESULT fdb_error_t fdb_future_get_cluster(FDBFuture* f, FDBCluster** out_cluster); DLLEXPORT WARN_UNUSED_RESULT fdb_error_t fdb_future_get_database(FDBFuture* f, FDBDatabase** out_database); DLLEXPORT WARN_UNUSED_RESULT FDBFuture* fdb_create_cluster(const char* cluster_file_path); DLLEXPORT void fdb_cluster_destroy(FDBCluster* c); DLLEXPORT WARN_UNUSED_RESULT fdb_error_t fdb_cluster_set_option(FDBCluster* c, FDBClusterOption option, uint8_t const* value, int value_length); DLLEXPORT WARN_UNUSED_RESULT FDBFuture* fdb_cluster_create_database(FDBCluster* c, uint8_t const* db_name, int db_name_length); #else #define fdb_future_get_cluster(f, oc) FDB_REMOVED_FUNCTION #define fdb_future_get_database(f, od) FDB_REMOVED_FUNCTION #define fdb_create_cluster(cfp) FDB_REMOVED_FUNCTION #define fdb_cluster_destroy(c) FDB_REMOVED_FUNCTION #define fdb_cluster_set_option(c, o, v, vl) FDB_REMOVED_FUNCTION #define fdb_cluster_create_database(c, dn, dnl) FDB_REMOVED_FUNCTION #endif #if FDB_API_VERSION < 23 DLLEXPORT WARN_UNUSED_RESULT fdb_error_t fdb_future_get_error(FDBFuture* f, const char** out_description /* = NULL */); DLLEXPORT fdb_bool_t fdb_future_is_error(FDBFuture* f); #else #define fdb_future_is_error(x) FDB_REMOVED_FUNCTION #endif #if FDB_API_VERSION < 14 DLLEXPORT WARN_UNUSED_RESULT fdb_error_t fdb_future_get_keyvalue_array(FDBFuture* f, FDBKeyValue const** out_kv, int* out_count); DLLEXPORT WARN_UNUSED_RESULT FDBFuture* fdb_transaction_get(FDBTransaction* tr, uint8_t const* key_name, int key_name_length); DLLEXPORT WARN_UNUSED_RESULT FDBFuture* fdb_transaction_get_key(FDBTransaction* tr, uint8_t const* key_name, int key_name_length, fdb_bool_t or_equal, int offset); DLLEXPORT WARN_UNUSED_RESULT fdb_error_t fdb_setup_network(const char* local_address); DLLEXPORT void fdb_transaction_set_option(FDBTransaction* tr, FDBTransactionOption option); DLLEXPORT WARN_UNUSED_RESULT FDBFuture* fdb_transaction_get_range(FDBTransaction* tr, uint8_t const* begin_key_name, int begin_key_name_length, uint8_t const* end_key_name, int end_key_name_length, int limit); DLLEXPORT WARN_UNUSED_RESULT FDBFuture* fdb_transaction_get_range_selector(FDBTransaction* tr, uint8_t const* begin_key_name, int begin_key_name_length, fdb_bool_t begin_or_equal, int begin_offset, uint8_t const* end_key_name, int end_key_name_length, fdb_bool_t end_or_equal, int end_offset, int limit); #else #define fdb_transaction_get_range_selector(tr, bkn, bknl, boe, bo, ekn, eknl, eoe, eo, lim) FDB_REMOVED_FUNCTION #endif #ifdef __cplusplus } #endif #endif