Couchbase C Client  3.0.7
Asynchronous C Client for Couchbase
example/libeventdirect/main.c

Shows how to integrate the library with an external event loop

/* -*- Mode: C; tab-width: 4; c-basic-offset: 4; indent-tabs-mode: nil -*- */
/*
* Copyright 2012-2020 Couchbase, Inc.
*
* 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.
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <event2/event.h>
const char key[] = "foo";
lcb_SIZE nkey = sizeof(key);
const char val[] = "{\"answer\":42}";
lcb_SIZE nval = sizeof(val);
int nreq = 1;
int nresp = 1;
int interval = 0;
struct event *timer = NULL;
static void bootstrap_callback(lcb_INSTANCE *instance, lcb_STATUS err)
{
lcb_CMDSTORE *cmd;
if (err != LCB_SUCCESS) {
fprintf(stderr, "ERROR: %s\n", lcb_strerror_short(err));
exit(EXIT_FAILURE);
}
printf("successfully bootstrapped\n");
fflush(stdout);
/* Since we've got our configuration, let's go ahead and store a value */
lcb_cmdstore_create(&cmd, LCB_STORE_UPSERT);
lcb_cmdstore_key(cmd, key, nkey);
lcb_cmdstore_value(cmd, val, nval);
err = lcb_store(instance, NULL, cmd);
lcb_cmdstore_destroy(cmd);
if (err != LCB_SUCCESS) {
fprintf(stderr, "Failed to set up store request: %s\n", lcb_strerror_short(err));
exit(EXIT_FAILURE);
}
}
static void get_callback(lcb_INSTANCE *instance, int cbtype, const lcb_RESPGET *rg)
{
const char *value;
size_t nvalue;
lcb_STATUS rc = lcb_respget_status(rg);
if (rc != LCB_SUCCESS) {
fprintf(stderr, "Failed to get key: %s\n", lcb_strerror_short(rc));
exit(EXIT_FAILURE);
}
lcb_respget_value(rg, &value, &nvalue);
printf("%d. retrieved the key 'foo', value: %.*s\n", nresp, (int)nvalue, value);
fflush(stdout);
nresp--;
if (nresp == 0) {
printf("stopping the loop\n");
event_base_loopbreak((void *)lcb_get_cookie(instance));
}
(void)cbtype;
}
static void schedule_timer();
static void timer_callback(int fd, short event, void *arg)
{
lcb_INSTANCE *instance = arg;
lcb_CMDGET *gcmd;
lcb_cmdget_create(&gcmd);
lcb_cmdget_key(gcmd, key, nkey);
rc = lcb_get(instance, NULL, gcmd);
lcb_cmdget_destroy(gcmd);
if (rc != LCB_SUCCESS) {
fprintf(stderr, "Failed to schedule get request: %s\n", lcb_strerror_short(rc));
exit(EXIT_FAILURE);
}
(void)fd;
(void)event;
schedule_timer();
}
static void schedule_timer()
{
struct timeval tv;
if (!nreq) {
return;
}
tv.tv_sec = interval;
tv.tv_usec = 0;
evtimer_add(timer, &tv);
nreq--;
}
static void store_callback(lcb_INSTANCE *instance, int cbtype, const lcb_RESPSTORE *resp)
{
lcb_STATUS rc = lcb_respstore_status(resp);
if (rc != LCB_SUCCESS) {
fprintf(stderr, "Failed to store key: %s\n", lcb_strerror_short(rc));
exit(EXIT_FAILURE);
}
printf("stored key 'foo'\n");
fflush(stdout);
{
struct event_base *evbase = (struct event_base *)lcb_get_cookie(instance);
printf("try to get value %d times with %dsec interval\n", nreq, interval);
timer = evtimer_new(evbase, timer_callback, instance);
schedule_timer();
}
(void)cbtype;
}
static lcb_io_opt_t create_libevent_io_ops(struct event_base *evbase)
{
struct lcb_create_io_ops_st ciops;
lcb_io_opt_t ioops;
lcb_STATUS error;
memset(&ciops, 0, sizeof(ciops));
ciops.v.v0.type = LCB_IO_OPS_LIBEVENT;
ciops.v.v0.cookie = evbase;
error = lcb_create_io_ops(&ioops, &ciops);
if (error != LCB_SUCCESS) {
fprintf(stderr, "Failed to create an IOOPS structure for libevent: %s\n", lcb_strerror_short(error));
exit(EXIT_FAILURE);
}
return ioops;
}
static lcb_INSTANCE *create_libcouchbase_handle(lcb_io_opt_t ioops, int argc, char **argv)
{
lcb_INSTANCE *instance;
lcb_STATUS error;
lcb_CREATEOPTS *options = NULL;
lcb_createopts_create(&options, LCB_TYPE_BUCKET);
/* If NULL, will default to localhost */
if (argc > 1) {
lcb_createopts_connstr(options, argv[1], strlen(argv[1]));
}
if (argc > 3) {
lcb_createopts_credentials(options, argv[3], strlen(argv[3]), argv[2], strlen(argv[2]));
}
lcb_createopts_io(options, ioops);
error = lcb_create(&instance, options);
lcb_createopts_destroy(options);
if (error != LCB_SUCCESS) {
fprintf(stderr, "Failed to create a libcouchbase instance: %s\n", lcb_strerror_short(error));
exit(EXIT_FAILURE);
}
/* Set up the callbacks */
lcb_set_bootstrap_callback(instance, bootstrap_callback);
if ((error = lcb_connect(instance)) != LCB_SUCCESS) {
fprintf(stderr, "Failed to connect libcouchbase instance: %s\n", lcb_strerror_short(error));
lcb_destroy(instance);
exit(EXIT_FAILURE);
}
return instance;
}
/* This example shows how we can hook ourself into an external event loop.
* You may find more information in the blogpost: http://goo.gl/fCTrX */
int main(int argc, char **argv)
{
struct event_base *evbase = event_base_new();
lcb_io_opt_t ioops = create_libevent_io_ops(evbase);
lcb_INSTANCE *instance = create_libcouchbase_handle(ioops, argc, argv);
if (argc > 4) {
nreq = nresp = atoi(argv[4]);
}
if (argc > 5) {
interval = atoi(argv[5]);
}
/*Store the event base as the user cookie in our instance so that
* we may terminate the program when we're done */
lcb_set_cookie(instance, evbase);
/* Run the event loop */
event_base_loop(evbase, 0);
/* Cleanup */
lcb_destroy(instance);
if (timer) {
evtimer_del(timer);
}
event_base_free(evbase);
return EXIT_SUCCESS;
}
lcb_strerror_short
LCB_INTERNAL_API const char * lcb_strerror_short(lcb_STATUS error)
Get a shorter textual description of an error message.
LCB_IO_OPS_LIBEVENT
@ LCB_IO_OPS_LIBEVENT
Integrate with the libevent loop.
Definition: iops.h:902
lcb_RESPSTORE
struct lcb_RESPSTORE_ lcb_RESPSTORE
Schedule a single storage request.
Definition: couchbase.h:940
lcb_set_bootstrap_callback
lcb_bootstrap_callback lcb_set_bootstrap_callback(lcb_INSTANCE *instance, lcb_bootstrap_callback callback)
Set the callback for notification of success or failure of initial connection.
lcb_create_io_ops_st
Definition: iops.h:930
LCB_CALLBACK_STORE
@ LCB_CALLBACK_STORE
lcb_store()
Definition: couchbase.h:469
lcb_connect
lcb_STATUS lcb_connect(lcb_INSTANCE *instance)
Schedule the initial connection This function will schedule the initial connection for the handle.
lcb_create
lcb_STATUS lcb_create(lcb_INSTANCE **instance, const lcb_CREATEOPTS *options)
Create an instance of lcb.
lcb_create_io_ops
lcb_STATUS lcb_create_io_ops(lcb_io_opt_t *op, const struct lcb_create_io_ops_st *options)
Create a new instance of one of the library-supplied io ops types.
lcb_STATUS
lcb_STATUS
Error codes returned by the library.
Definition: error.h:207
lcb_INSTANCE
struct lcb_st lcb_INSTANCE
Library handle representing a connection to a cluster and its data buckets.
Definition: couchbase.h:35
LCB_CALLBACK_GET
@ LCB_CALLBACK_GET
lcb_get()
Definition: couchbase.h:468
lcb_destroy_io_ops
lcb_STATUS lcb_destroy_io_ops(lcb_io_opt_t op)
Destroy the plugin handle created by lcb_create_io_ops()
lcb_RESPGET
struct lcb_RESPGET_ lcb_RESPGET
Command for retrieving a single item.
Definition: couchbase.h:684
couchbase.h
Main header file for Couchbase.
LCB_STORE_UPSERT
@ LCB_STORE_UPSERT
The default storage mode.
Definition: couchbase.h:856
lcb_destroy
void lcb_destroy(lcb_INSTANCE *instance)
Destroy (and release all allocated resources) an instance of lcb.
LCB_TYPE_BUCKET
@ LCB_TYPE_BUCKET
Handle for data access (default)
Definition: couchbase.h:255
lcb_install_callback
lcb_RESPCALLBACK lcb_install_callback(lcb_INSTANCE *instance, int cbtype, lcb_RESPCALLBACK cb)
lcb_RESPCALLBACK
void(* lcb_RESPCALLBACK)(lcb_INSTANCE *instance, int cbtype, const lcb_RESPBASE *resp)
Callback invoked for responses.
Definition: couchbase.h:551