2

I'm trying to implement a C application that will monitor writes / modifications / new documents events happening on a couchbase remote cluster coming from a different application. I am now familiar with couchbase C SDK and synchronous instances but I have trouble combining it with libevent for asynchronous I/O.

I read couchbase libevent plugin documentation and the external event loop integration example but I cannot grasp how I would tell my event_base that, for instance:

Monitor this file on this bucket and send me a callback when it's modified

Here's what I do so far:

Firstly, I create my libevent IO option

struct event_base *mEvbase = event_base_new();
lcb_t instance;
lcb_error_t err;

struct lcb_create_io_ops_st ciops;
lcb_io_opt_t ioops;

memset(&ciops, 0, sizeof(ciops));
ciops.v.v0.type = LCB_IO_OPS_LIBEVENT;
ciops.v.v0.cookie = mEvbase;

err = lcb_create_libevent_io_opts(0, &ioops, mEvbase);
if (err != LCB_SUCCESS) {
    ERRORMSG0("Failed to create an IOOPS structure for libevent: %s\n", lcb_strerror(NULL, error));
}

and then I create my instance:

struct lcb_create_st create_options;

std::string host = std::string("couchbase://192.168.130.10/");
host.append(bucket);
const char password[] = "password";

create_options.version = 3;
create_options.v.v3.connstr = host.c_str();
create_options.v.v3.passwd = password;
create_options.v.v3.io = ioops;

//Creating a lcb instance
err = lcb_create(&instance, &create_options);
if (err != LCB_SUCCESS) {
    die(NULL, "Couldn't create couchbase handler\n", err);
    return;
}

/* Assign the handlers to be called for the operation types */
lcb_set_bootstrap_callback(instance, bootstrap_callback);
lcb_set_get_callback(instance, generic_get_callback);
lcb_set_store_callback(instance, generic_store_callback);

and then I schedule a connection.

//We now schedule a connection to the server
err = lcb_connect(instance);
if (err != LCB_SUCCESS) {
    die(instance, "Couldn't schedule connection\n", err);
    lcb_destroy(instance);
}
lcb_set_cookie(instance, mEvbase);

I use libcouchbase version 2.0.17, libevent core version 2.0.so.5.1.9 and libevent extra version 2.0.so.5.1.9. With the code above, my instance cannot connect to couchbase. I get the following warnings:

event_pending: event has no event_base set. 
event_add: event has no event_base set.

So two problems here: I can't connect using the above code and I don't know which direction to go to start receiving events. If anyone point me towards a link or a coded example of this simple case that would unblock me.

Starscream
  • 1,128
  • 1
  • 9
  • 22
  • You would be requesting notification from the server when an item is modified. Unfortunately this is currently not supported in the SDK itself. You can take a look at TAP or DCP to suit your needs, however. Please clarify if this is not what you want. – Mark Nunberg Oct 10 '14 at 02:38
  • Thank you for your answer. Can you give me a link to TAP or DCP because I have no idea what it is and Google won't help. – Starscream Oct 10 '14 at 07:16
  • 1
    TAP and DCP are internal protocols that the nodes use to replicate data between one another. While these are internal protocols you may still utilize them. Currently the Java SDK has a TAP API. The C SDK does not have an interface for TAP currently. See http://www.couchbase.com/autodocs/couchbase-java-client-1.1.4/com/couchbase/client/TapClient.html – Mark Nunberg Oct 10 '14 at 18:28
  • Check that the `libcouchbase_libevent.so` plugin is linked to the same libevent being used by libcouchbase. I am not sure where these warnings are coming from, but they may be from your code or libevent directly (we don't have such warnings in the library core). – Mark Nunberg Oct 11 '14 at 03:48
  • Additionally, set the `LCB_LOGLEVEL` environment variable to `5` for more verbose logging and an idea of what may be happening. – Mark Nunberg Oct 11 '14 at 03:51
  • Thank you for your time. So I added the environment variable but not additional logs. I don't understand your comment asking to check wether the plugin `libcouchbase_libevent.so` was linked to the same libevent used by `libcouchbase`. All I know is I had to cheat in order to have the plugin `libcouchbase_libevent.so` work. I manually installed libevent 2.0 (make/make install) and libcouchbase_libevent.rpm was looking for libevent-1.4 dependency so I had to manually create a link called `libevent-1.4.so.2 -> libevent.so (2.0)` to make it work. This might be related. – Starscream Oct 13 '14 at 08:16
  • That is likely related. The library is compiled against the 1.4 API/ABI, while your application is using the 2.0 ABI. If you are using libevent 1.4, what I would try doing is compiling the library itself (libcouchbase) from source as well and see if this works – Mark Nunberg Oct 13 '14 at 15:18
  • If this resolves your issue please let me place it as an answer :) – Mark Nunberg Oct 14 '14 at 16:12
  • I actually am using libevent 2.0 it's just that for some reason libcouchbase_libevent was desperately looking for `libevent-1.4.so` and I "hacked" it by creating a symlink called `libevent-1.4.so` pointing to libevent 2.0. I didn't have time to try everything but you can add your answer it did help me a lot. – Starscream Oct 15 '14 at 06:58

1 Answers1

2

Ensure that you are using the same libevent version for both the library and your application. Installing the packages from the repository, you will need to align with the libevent version used therein (e.g. ldd /usr/lib64/libcouchbase_libevent.so). Keep in mind that this must be of the same ABI (so for example, using libevent's 2.0 -> 1.4 compat layer will not work, as the two versions contain different ABIs, and using a libcouchbase_libevent.so linked against 1.4 will break under 2.0).

For the full exchange, see the the comments on the question :)

Mark Nunberg
  • 3,551
  • 15
  • 18