1 #define LCB_NO_DEPR_CXX_CTORS
2 #undef NDEBUG
3
4 #include <libcouchbase/couchbase.h>
5 #include <libcouchbase/api3.h>
6 #include <assert.h>
7 #include <string.h>
8 #include <cstdlib>
9 #include <string>
10 #include <vector>
11
generic_callback(lcb_t,int type,const lcb_RESPBASE * rb)12 static void generic_callback(lcb_t, int type, const lcb_RESPBASE *rb)
13 {
14 printf("Got callback for %s\n", lcb_strcbtype(type));
15
16 if (rb->rc != LCB_SUCCESS && rb->rc != LCB_SUBDOC_MULTI_FAILURE) {
17 printf("Failure: 0x%x\n", rb->rc);
18 abort();
19 }
20
21 if (type == LCB_CALLBACK_GET) {
22 const lcb_RESPGET *rg = (const lcb_RESPGET *)rb;
23 printf("Result is: %.*s\n", (int)rg->nvalue, rg->value);
24 } else if (type == LCB_CALLBACK_SDLOOKUP || type == LCB_CALLBACK_SDMUTATE) {
25 lcb_SDENTRY ent;
26 size_t iter = 0;
27 size_t oix = 0;
28 const lcb_RESPSUBDOC *resp = reinterpret_cast<const lcb_RESPSUBDOC*>(rb);
29 while (lcb_sdresult_next(resp, &ent, &iter)) {
30 size_t index = oix++;
31 if (type == LCB_CALLBACK_SDMUTATE) {
32 index = ent.index;
33 }
34 printf("[%lu]: 0x%x. %.*s\n",
35 index, ent.status, (int)ent.nvalue, ent.value);
36 }
37 }
38 }
39
40 // cluster_run mode
41 #define DEFAULT_CONNSTR "couchbase://localhost"
42
main(int argc,char ** argv)43 int main(int argc, char **argv) {
44 lcb_create_st crst = { 0 };
45 crst.version = 3;
46 if (argc > 1) {
47 crst.v.v3.connstr = argv[1];
48 } else {
49 crst.v.v3.connstr = DEFAULT_CONNSTR;
50 }
51 if (argc > 2) {
52 crst.v.v3.username = argv[2];
53 } else {
54 crst.v.v3.username = "Administrator";
55 }
56 if (argc > 3) {
57 crst.v.v3.passwd = argv[3];
58 } else {
59 crst.v.v3.passwd = "password";
60 }
61
62 lcb_t instance;
63 lcb_error_t rc = lcb_create(&instance, &crst);
64 assert(rc == LCB_SUCCESS);
65
66 rc = lcb_connect(instance);
67 assert(rc == LCB_SUCCESS);
68 lcb_wait(instance);
69 rc = lcb_get_bootstrap_status(instance);
70 assert(rc == LCB_SUCCESS);
71
72 // Install generic callback
73 lcb_install_callback3(instance, LCB_CALLBACK_DEFAULT, generic_callback);
74
75 // Store an item
76 lcb_CMDSTORE scmd = { 0 };
77 scmd.operation = LCB_SET;
78 LCB_CMD_SET_KEY(&scmd, "key", 3);
79 const char *initval = "{\"hello\":\"world\"}";
80 LCB_CMD_SET_VALUE(&scmd, initval, strlen(initval));
81 rc = lcb_store3(instance, NULL, &scmd);
82 assert(rc == LCB_SUCCESS);
83
84 lcb_CMDSUBDOC mcmd = { 0 };
85 LCB_CMD_SET_KEY(&mcmd, "key", 3);
86
87 std::vector<lcb_SDSPEC> specs;
88 std::string bufs[10];
89
90 // Add some mutations
91 for (int ii = 0; ii < 5; ii++) {
92 std::string& path = bufs[ii * 2];
93 std::string& val = bufs[(ii * 2) + 1];
94 char pbuf[24], vbuf[24];
95
96 sprintf(pbuf, "pth%d", ii);
97 sprintf(vbuf, "\"Value_%d\"", ii);
98 path = pbuf;
99 val = vbuf;
100
101 lcb_SDSPEC spec = { 0 };
102 LCB_SDSPEC_SET_PATH(&spec, path.c_str(), path.size());
103 LCB_CMD_SET_VALUE(&spec, val.c_str(), val.size());
104 spec.sdcmd = LCB_SDCMD_DICT_UPSERT;
105 specs.push_back(spec);
106 }
107
108 mcmd.specs = specs.data();
109 mcmd.nspecs = specs.size();
110 rc = lcb_subdoc3(instance, NULL, &mcmd);
111 assert(rc == LCB_SUCCESS);
112
113 // Reset the specs
114 specs.clear();
115 for (int ii = 0; ii < 5; ii++) {
116 char pbuf[24];
117 std::string& path = bufs[ii];
118 sprintf(pbuf, "pth%d", ii);
119 path = pbuf;
120
121 lcb_SDSPEC spec = { 0 };
122 LCB_SDSPEC_SET_PATH(&spec, path.c_str(), path.size());
123 spec.sdcmd = LCB_SDCMD_GET;
124 specs.push_back(spec);
125 }
126
127 lcb_SDSPEC spec2 = { 0 };
128 LCB_SDSPEC_SET_PATH(&spec2, "dummy", 5);
129 spec2.sdcmd = LCB_SDCMD_GET;
130 specs.push_back(spec2);
131 mcmd.specs = specs.data();
132 mcmd.nspecs = specs.size();
133 rc = lcb_subdoc3(instance, NULL, &mcmd);
134 assert(rc == LCB_SUCCESS);
135
136 lcb_CMDGET gcmd = { 0 };
137 LCB_CMD_SET_KEY(&gcmd, "key", 3);
138 rc = lcb_get3(instance, NULL, &gcmd);
139 assert(rc == LCB_SUCCESS);
140
141 lcb_wait(instance);
142 lcb_destroy(instance);
143 }
144