R SDK client?

Hi all,

First of all thanks for this fantastic work.
I am planning to create a new couchbase SDK client for the R language. The idea is to use a wrapper around the C library libcouchbase.

I am confused with some notions especially the callback. Here my pseudo code with some questions as comments.

1 - rclient = RCouchebase(...)
          --> lcb_create(...)    
          // should I call this one per session?
2-  rclient.Connect()
          --> lcb_connect()
          --> lcb_wait()
3- rclient.get(...)
          --> lcb_get(...)       
         // should I call a callback here using lcb_set_get_callback?
4- rclient.set() 
          --> lcb_set(...)

I am simplifying my idea to some basic functions (constructor,connect,get and set). Under each R function I write the effective C call(s). Does this look right? I don't have any problem to call the C code from R but my question is more about the general workflow to call libcouchbase functions to do something similar to others SDK (python for example).

1 Answer

« Back to question.


1 - rclient = RCouchebase(...)
          --> lcb_create(...)    
          // should I call this one per session?


Yeah, lcb_create gives you connection handle you should use for further ops. Also if you need to connect to different buckets or clusters, you have to create different handle for each of them.


3- rclient.get(...)
          --> lcb_get(...)       
         // should I call a callback here using lcb_set_get_callback?


You should setup callbacks right after successful creation of the handle, and before sending corresponding command. You can do it once if your callback is the same.

If your R client is not supposed to do asynchronous IO, you can make synchronous interface and hide callbacks from the R space. Like this:

- rclient.get(key)

will contain the following code (this is simplified version, of course without any R glue to convert types to C)

lcb_get_cmd_t cmd;
const lcb_get_cmd_t *commands[1];
commands[0] = &cmd;
memset(&cmd, 0, sizeof(cmd));
cmd.v.v0.key = key;
cmd.v.v0.nkey = strlen(key);
 
lcb_error_t rc;
char *result;
rc = lcb_get(instance, &result, 1, commands);
if (rc != LCB_SUCCESS) {
    fprintf(stderr, "Failed to get: %s\n", lcb_strerror(NULL, rc));
    exit(EXIT_FAILURE);
}

What this code shows is that you can create and pass as cookie argument your custom structure for each command. Here it is just pointer to C string result. The callback should extract this pointer from cookie and fill with the document body, this simplified code assumes that the body won't have NUL terminator, therefore doesn't pass document length from the callback. The text of callback can be like this

static void get_callback(lcb_t instance,
                         const void *cookie,
                         lcb_error_t status,
                         const lcb_get_resp_t *item)
{
    char **res = (char **)cookie;
    if (status == LCB_SUCCESS) {
        *res = malloc(item->v.v0.nbytes);
        memcpy(*res, item->v.v0.nbytes, item->v.v0.nbytes);
    } else {
        *res = NULL;
    }
}

Well.

What about lcb_connect? . You just mention lcb_create in your answer.
And do I need to set a callback for lcb_set?

You have to set callback for each operation you are wrapping. So if there will be rclient.set(), you have to setup that callback

And yes, you need to call lcb_connect to connect your handle to the cluster, i.e. establish socket connection.

In general, your client might combine create+connect into single operation (like construction of the object). This is how for example ruby client behaves

Thanks for your reactivity.
I guess I should init :
1- creation
2- connection
3- all my callabacks

In my Constructor , I should have something like :

 RCouchbase(...){
l     cb_create(&instance, &options);
      err = lcb_connect(instance);
      err = lcb_wait(instance);  ### the call to wait is it correct here?
     lcb_set_get_callback(....)
}

yes, you have to run lcb_wait after lcb_connect.

Thanks.

Out of curiosity, is your code hosted somewhere online? Is it Open Source? This sounds cool!

Is not yet hosted. But is will be definitely an open source SDK once I get a first stable version.