Skip to content

Commit

Permalink
http://whatthecommit.com/de3a706f3336bd6b3c70fda43753f859
Browse files Browse the repository at this point in the history
  • Loading branch information
mnunberg committed Sep 29, 2015
1 parent 4a4ae42 commit 5097154
Show file tree
Hide file tree
Showing 17 changed files with 768 additions and 3 deletions.
68 changes: 68 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,3 +2,71 @@

These examples are intended to be linked to from within the developer guide.
They are currently cross-referenced by language.

Each example should be fully self-contained and executable. For languages which have a significant setup, the example may be split into multiple files, but should still be executable. Error handling is optional but should be be at least hinted at.

### Basic Connection
This example should show how to connect to a remote Couchbase cluster and bucket

[C](c/connecting.c) |
[Python](python/connecting.py) |
Java |
.NET |
Go |
node.js

### Updating/Storing
This example should show how to store an item into a cluster

[C](c/updating.c) |
[Python](python/updating.py) |
Java |
.NET |
Go |
node.js

### Retrieving
This example should show how to get items out of the cluster

[C](c/retrieving.cc) |
[Python](python/retrieving.py) |
Java |
.NET |
Go |
node.js

### Counter
This example should show how to initialize and update a counter

[C](c/counter.cc) |
[Python](python/counter.py) |
Java |
.NET |
Go |
node.js

### Query with criteria
This example should show how to perform a simple query against the travel-sample bucket. The query is something like:

```
query = N1QLQuery('SELECT airportname, city, country FROM `travel-sample` '
'WHERE type="airport" AND city="Reno"')
```

[C](c/query-criteria.cc) |
[Python](python/query-criteria.py) |
Java |
.NET |
Go |
node.js


### Query with placeholders
This example should demonstrate how to use placeholders, and also the advantages they afford, perhaps by abstracting a given query away as a function, and passing a function parameter down as a query parameter

[C](c/query-placeholders.cc) |
[Python](python/query-placeholders.py) |
Java |
.NET |
Go |
node.js
9 changes: 9 additions & 0 deletions c/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
updating
connecting
counter
retrieving
expiration
query-placeholders
query-create-index
query-criteria
*.dSYM
10 changes: 9 additions & 1 deletion c/Makefile
Original file line number Diff line number Diff line change
@@ -1,3 +1,11 @@
all: connecting
PROGS=connecting updating retrieving query-create-index query-criteria \
query-placeholders counter expiration

all: $(PROGS)

clean:
rm -f $(PROGS)
rm -rf *.dSYM

CPPFLAGS=-Wall -g
LDFLAGS=-lcouchbase
78 changes: 78 additions & 0 deletions c/counter.cc
Original file line number Diff line number Diff line change
@@ -0,0 +1,78 @@
#include <libcouchbase/couchbase.h>
#include <libcouchbase/api3.h>
#include <stdio.h>

static void
counter_callback(lcb_t, int, const lcb_RESPBASE *rb)
{
const lcb_RESPCOUNTER *resp = reinterpret_cast<const lcb_RESPCOUNTER*>(rb);
if (resp->rc != LCB_SUCCESS) {
fprintf(stderr, "Couldn't perform counter operation!\n");
fprintf(stderr, "Error code 0x%x (%s)\n", resp->rc,
lcb_strerror(NULL, resp->rc));
return;
}

printf("Current counter value is %llu\n", resp->value);
}


// Removes the counter. This is optional, but is helpful for demonstrative
// purposes so that we always start off with a fresh counter
static void
remove_counter(lcb_t instance, const char *docid)
{
lcb_CMDREMOVE cmd = { 0 };
LCB_CMD_SET_KEY(&cmd, docid, strlen(docid));
lcb_sched_enter(instance);
lcb_remove3(instance, NULL, &cmd);
lcb_sched_leave(instance);
lcb_wait(instance);
}

int
main(int, char **)
{
lcb_t instance;
lcb_create_st crst;
lcb_error_t rc;
memset(&crst, 0, sizeof crst);

crst.version = 3;
crst.v.v3.connstr = "couchbase://10.0.0.31/default";
rc = lcb_create(&instance, &crst);
rc = lcb_connect(instance);
lcb_wait(instance);
rc = lcb_get_bootstrap_status(instance);

lcb_install_callback3(instance, LCB_CALLBACK_COUNTER, counter_callback);

lcb_sched_enter(instance);

const char *docid = "docid";
remove_counter(instance, docid);

lcb_CMDCOUNTER cmd = { 0 };
LCB_CMD_SET_KEY(&cmd, docid, strlen(docid));
cmd.initial = 100;
cmd.delta = 20;
cmd.create = 1;

rc = lcb_counter3(instance, NULL, &cmd);
lcb_sched_leave(instance);
lcb_wait(instance);

lcb_sched_enter(instance);
cmd.delta = 1;
rc = lcb_counter3(instance, NULL, &cmd);
lcb_sched_leave(instance);
lcb_wait(instance);

lcb_sched_enter(instance);
cmd.delta = -50;
rc = lcb_counter3(instance, NULL, &cmd);
lcb_sched_leave(instance);
lcb_wait(instance);

lcb_destroy(instance);
}
128 changes: 128 additions & 0 deletions c/expiration.cc
Original file line number Diff line number Diff line change
@@ -0,0 +1,128 @@
#include <libcouchbase/couchbase.h>
#include <libcouchbase/api3.h>

#ifdef _WIN32
#include <windows.h>
#define sleep(s) Sleep(s/1000)
#else
#include <unistd.h>
#endif

static void
op_callback(lcb_t, int cbtype, const lcb_RESPBASE *resp)
{
if (resp->rc == LCB_SUCCESS) {
printf("Operation (type=%d) OK\n", cbtype);
} else {
printf("Operation (type=%d) Failed (%s)\n",
cbtype, lcb_strerror(NULL, resp->rc));
}

if (cbtype == LCB_CALLBACK_GET) {
const lcb_RESPGET *rg = reinterpret_cast<const lcb_RESPGET*>(resp);
if (resp->rc == LCB_SUCCESS) {
printf("Got value %.*s\n", (int)rg->nvalue, rg->value);
}
}
}

static void
store_key(lcb_t instance, const char *key, const char *value, unsigned exp=0)
{
lcb_CMDSTORE scmd = { 0 };
LCB_CMD_SET_KEY(&scmd, key, strlen(key));
LCB_CMD_SET_VALUE(&scmd, value, strlen(value));
scmd.exptime = exp; // Only live for 2 seconds!
scmd.operation = LCB_SET;

lcb_sched_enter(instance);
lcb_store3(instance, NULL, &scmd);
lcb_sched_leave(instance);
lcb_wait(instance);
}

static void
get_or_touch(lcb_t instance, const char *key, unsigned exp=0, bool get=false)
{
union {
lcb_CMDBASE base;
lcb_CMDGET get;
lcb_CMDTOUCH touch;
} u;

memset(&u, 0, sizeof u);

LCB_CMD_SET_KEY(&u.base, key, strlen(key));
u.base.exptime = exp;

lcb_sched_enter(instance);

if (get) {
lcb_get3(instance, NULL, &u.get);
} else {
lcb_touch3(instance, NULL, &u.touch);
}

lcb_sched_leave(instance);
lcb_wait(instance);
}

int
main(int, char **)
{
lcb_t instance;
lcb_create_st crst;
lcb_error_t rc;

memset(&crst, 0, sizeof crst);
crst.version = 3;
crst.v.v3.connstr = "couchbase://10.0.0.31/default";

rc = lcb_create(&instance, &crst);
rc = lcb_connect(instance);
lcb_wait(instance);
rc = lcb_get_bootstrap_status(instance);

// You can actually use the same callback for multiple types of operations.
// The second parameter is the type of callback being invoked. You can
// then cast the return type to the more specific struct.
lcb_install_callback3(instance, LCB_CALLBACK_DEFAULT, op_callback);

const char *key = "docid";
const char *value = "{\"some\":\"value\"}";

// First store with an expiry of 1 second
printf("Storing with an expiration of 2\n");
store_key(instance, key, value, 2);
printf("Getting key immediately after store..\n");
get_or_touch(instance, key, 0, true);

printf("Sleeping for 4 seconds..\n");
sleep(4);
printf("Getting key again (should fail)\n");
get_or_touch(instance, key);

printf("Storing key again (without expiry)\n");
store_key(instance, key, value);
printf("Using get-and-touch to retrieve key and modify expiry\n");
get_or_touch(instance, key, 1, true);

printf("Sleeping for another 4 seconds\n");
sleep(4);
printf("Getting key again (should fail)\n");
get_or_touch(instance, key, 0, true);

printf("Storing key again (without expiry)\n");
store_key(instance, key, value);

printf("Touching key (without get). Setting expiry for 1 second\n");
get_or_touch(instance, key, 1, false);

printf("Sleeping for 4 seconds\n");
sleep(4);

printf("Getting again... (should fail)\n");
get_or_touch(instance, key, 0, true);

lcb_destroy(instance);
}
2 changes: 0 additions & 2 deletions c/gitignore

This file was deleted.

43 changes: 43 additions & 0 deletions c/query-create-index.cc
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
#include <libcouchbase/couchbase.h>
#include <libcouchbase/n1ql.h>

extern "C" {
static void
query_callback(lcb_t, int, const lcb_RESPN1QL *resp)
{
// This might also fail if the index is already created!
if (resp->rc != LCB_SUCCESS) {
fprintf(stderr, "N1QL query failed (%s)\n", lcb_strerror(NULL, resp->rc));
}
printf("Result text: %.*s\n", (int)resp->nrow, resp->row);
}
}

int
main(int, char **)
{
lcb_t instance;
struct lcb_create_st crst;
lcb_error_t rc;
lcb_CMDN1QL cmd = { 0 };
lcb_N1QLPARAMS *params = NULL;

memset(&crst, 0, sizeof crst);
crst.version = 3;
crst.v.v3.connstr = "couchbase://10.0.0.31/travel-sample";
rc = lcb_create(&instance, &crst); // Check rc
rc = lcb_connect(instance); // Check rc
lcb_wait(instance);
rc = lcb_get_bootstrap_status(instance); // Check rc

params = lcb_n1p_new();
rc = lcb_n1p_setstmtz(params, "CREATE PRIMARY INDEX ON `travel-sample`");

cmd.callback = query_callback;
lcb_n1p_mkcmd(params, &cmd);
rc = lcb_n1ql_query(instance, NULL, &cmd); // Check RC
lcb_wait(instance);

lcb_n1p_free(params);
lcb_destroy(instance);
}
Loading

0 comments on commit 5097154

Please sign in to comment.