Skip to content

Instantly share code, notes, and snippets.

@josephg
Created February 4, 2019 21:54
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 2 You must be signed in to fork a gist
  • Save josephg/7fa89ec0f7cfa2d5dd66c352dd0bebfa to your computer and use it in GitHub Desktop.
Save josephg/7fa89ec0f7cfa2d5dd66c352dd0bebfa to your computer and use it in GitHub Desktop.
Foundationdb C API example

This is a simple example program using the foundationdb C API. Its written & tested on macos; but it should be easy to adapt to work on BSD / linux.

This also demonstrates using libuv to integrate foundationdb into a run loop. Promises are run in the main libuv loop.

Compile with

$ clang test.c -Wall -lfdb_c -I/usr/local/include -luv
#include <stdio.h>
#include <unistd.h>
#include <assert.h>
#include <stdlib.h>
#include <pthread.h>
#include <uv.h>
#define FDB_API_VERSION 510
#include <foundationdb/fdb_c.h>
void chk(fdb_error_t err) {
if (err) {
fprintf(stderr, "Error: %s\n", fdb_get_error(err));
abort();
}
}
void warn(fdb_error_t err) {
if (err) fprintf(stderr, "Warning: %s\n", fdb_get_error(err));
}
void *run_net(void *_unused) {
chk(fdb_run_network());
return NULL;
}
FDBCluster* get_cluster() {
FDBFuture* f = fdb_create_cluster(NULL);
chk(fdb_future_block_until_ready(f));
FDBCluster* out;
chk(fdb_future_get_cluster(f, &out));
return out;
}
FDBDatabase* get_database(FDBCluster *cluster) {
FDBFuture* f = fdb_cluster_create_database(cluster, (const uint8_t *)"DB", 2);
chk(fdb_future_block_until_ready(f));
FDBDatabase* out;
chk(fdb_future_get_database(f, &out));
return out;
}
void cb(FDBFuture* vf, void* data) {
char *str = (char *)data;
printf("callback %s called\n", str);
if (((char *)data)[0] == 'v') {
const uint8_t *data;
int length;
chk(fdb_future_get_key(vf, &data, &length));
for (int i = 0; i < length; i++) {
printf("%d ", data[i]);
printf("\n");
}
}
//int64_t version = 0;
//warn(fdb_future_get_error(vf));
//printf("Version %lld\n", version);
}
FDBCluster* cluster;
FDBDatabase* database;
uv_loop_t mainloop;
void stuff() {
{
FDBTransaction* txn;
chk(fdb_database_create_transaction(database, &txn));
FDBFuture *f = fdb_transaction_watch(txn, (uint8_t *)"hi", 2);
chk(fdb_future_set_callback(f, cb, "watch"));
FDBFuture *cf = fdb_transaction_commit(txn);
chk(fdb_future_set_callback(cf, cb, "commit"));
}
//FDBFuture *vf = fdb_transaction_get_read_version(txn);
//fdb_future_cancel(vf);
/*
chk(fdb_future_block_until_ready(vf));
int64_t version;
chk(fdb_future_get_version(vf, &version));
printf("Version %lld\n", version);
*/
}
typedef struct {
FDBFuture *future;
uv_async_t async;
void *data;
} Ctx;
static void mt_cb(uv_async_t *async) {
printf("got main thread cb\n");
Ctx *ctx = (Ctx *)async->data;
char *d = (char *)ctx->data;
printf("%s\n", d);
if (d[0] == 'v') {
const uint8_t *data;
int length;
chk(fdb_future_get_key(ctx->future, &data, &length));
for (int i = 0; i < length; i++) {
printf("%d ", data[i]);
printf("\n");
}
}
fdb_future_destroy(ctx->future);
uv_close((uv_handle_t *)&ctx->async, NULL);
}
static void future_cb(FDBFuture *f, void *_ctx) {
printf("future_cb\n");
Ctx *ctx = (Ctx *)_ctx;
uv_async_send(&ctx->async);
}
void resolveFutureInMainLoop(FDBFuture *f, void *data) {
Ctx *ctx = malloc(sizeof(Ctx));
ctx->data = data;
ctx->future = f;
// TODO: Handle error on async_init failing. Probably just assert.
assert(0 == uv_async_init(&mainloop, &ctx->async, mt_cb));
ctx->async.data = ctx;
chk(fdb_future_set_callback(f, future_cb, ctx));
}
void getStamp() {
FDBTransaction* txn;
chk(fdb_database_create_transaction(database, &txn));
uint8_t bytes[20] = {};
bytes[10] = 123;
fdb_transaction_atomic_op(txn, (uint8_t *)"x", 1, bytes, sizeof(bytes), FDB_MUTATION_TYPE_SET_VERSIONSTAMPED_VALUE);
FDBFuture *vf = fdb_transaction_get_versionstamp(txn);
resolveFutureInMainLoop(vf, "v");
//chk(fdb_future_set_callback(vf, cb, "vstamp"));
FDBFuture *cf = fdb_transaction_commit(txn);
resolveFutureInMainLoop(cf, "c");
//chk(fdb_future_set_callback(cf, cb, "commit"));
}
int main() {
uv_loop_init(&mainloop);
fdb_select_api_version(FDB_API_VERSION);
chk(fdb_setup_network());
pthread_t net_thread;
assert(0 == pthread_create(&net_thread, NULL, run_net, NULL));
cluster = get_cluster();
database = get_database(cluster);
//stuff();
getStamp();
uv_run(&mainloop, UV_RUN_DEFAULT);
sleep(1);
chk(fdb_stop_network());
pthread_join(net_thread, NULL);
return 0;
}
@kirubasankars
Copy link

Please update this to latest version

@josephg
Copy link
Author

josephg commented May 15, 2020

Is this linked / depended on somewhere?

@gm42
Copy link

gm42 commented May 6, 2024

I made a simpler modern version here: https://gist.github.com/gm42/a61d2fff82b9dddc47a449579c9307b8

Using the FoundationDB V7.1+ API.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment