libcouchbase 1.0.4 → 1.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (106) hide show
  1. checksums.yaml +4 -4
  2. data/.travis.yml +11 -8
  3. data/ext/libcouchbase/CMakeLists.txt +1 -1
  4. data/ext/libcouchbase/README.markdown +38 -6
  5. data/ext/libcouchbase/RELEASE_NOTES.markdown +151 -0
  6. data/ext/libcouchbase/cmake/Modules/GenerateConfigDotH.cmake +2 -2
  7. data/ext/libcouchbase/cmake/Modules/GetVersionInfo.cmake +3 -3
  8. data/ext/libcouchbase/cmake/source_files.cmake +1 -0
  9. data/ext/libcouchbase/contrib/cJSON/cJSON.c +686 -288
  10. data/ext/libcouchbase/contrib/cJSON/cJSON.h +0 -0
  11. data/ext/libcouchbase/contrib/cbsasl/src/hash.c +17 -17
  12. data/ext/libcouchbase/contrib/cliopts/cliopts.c +76 -0
  13. data/ext/libcouchbase/contrib/cliopts/cliopts.h +66 -15
  14. data/ext/libcouchbase/contrib/genhash/genhash.c +1 -2
  15. data/ext/libcouchbase/contrib/lcb-jsoncpp/lcb-jsoncpp.cpp +4 -3
  16. data/ext/libcouchbase/example/instancepool/main.cc +12 -2
  17. data/ext/libcouchbase/example/libeventdirect/main.c +99 -25
  18. data/ext/libcouchbase/example/minimal/minimal.c +7 -5
  19. data/ext/libcouchbase/example/observe/durability.c +102 -0
  20. data/ext/libcouchbase/example/observe/observe.c +19 -6
  21. data/ext/libcouchbase/example/subdoc/subdoc-xattrs.c +1 -2
  22. data/ext/libcouchbase/include/libcouchbase/cntl-private.h +6 -8
  23. data/ext/libcouchbase/include/libcouchbase/cntl.h +84 -64
  24. data/ext/libcouchbase/include/libcouchbase/couchbase.h +295 -78
  25. data/ext/libcouchbase/include/libcouchbase/deprecated.h +2 -2
  26. data/ext/libcouchbase/include/libcouchbase/error.h +1 -1
  27. data/ext/libcouchbase/include/libcouchbase/iops.h +9 -9
  28. data/ext/libcouchbase/include/libcouchbase/ixmgmt.h +2 -2
  29. data/ext/libcouchbase/include/libcouchbase/n1ql.h +69 -7
  30. data/ext/libcouchbase/include/libcouchbase/vbucket.h +17 -0
  31. data/ext/libcouchbase/include/libcouchbase/views.h +3 -3
  32. data/ext/libcouchbase/include/memcached/protocol_binary.h +62 -1
  33. data/ext/libcouchbase/packaging/deb/control +1 -1
  34. data/ext/libcouchbase/packaging/rpm/libcouchbase.spec.in +37 -36
  35. data/ext/libcouchbase/src/bootstrap.cc +22 -8
  36. data/ext/libcouchbase/src/bucketconfig/bc_cccp.cc +1 -1
  37. data/ext/libcouchbase/src/bucketconfig/bc_http.cc +0 -1
  38. data/ext/libcouchbase/src/bucketconfig/confmon.cc +13 -8
  39. data/ext/libcouchbase/src/callbacks.c +2 -0
  40. data/ext/libcouchbase/src/cntl.cc +28 -17
  41. data/ext/libcouchbase/src/dns-srv.cc +1 -2
  42. data/ext/libcouchbase/src/dump.cc +4 -0
  43. data/ext/libcouchbase/src/errmap.h +89 -16
  44. data/ext/libcouchbase/src/handler.cc +28 -11
  45. data/ext/libcouchbase/src/http/http-priv.h +4 -1
  46. data/ext/libcouchbase/src/http/http.cc +3 -0
  47. data/ext/libcouchbase/src/instance.cc +1 -1
  48. data/ext/libcouchbase/src/internal.h +1 -0
  49. data/ext/libcouchbase/src/lcbio/connect.cc +2 -3
  50. data/ext/libcouchbase/src/lcbio/manager.cc +2 -2
  51. data/ext/libcouchbase/src/lcbio/ssl.h +10 -0
  52. data/ext/libcouchbase/src/mc/mcreq.c +8 -0
  53. data/ext/libcouchbase/src/mcserver/mcserver.cc +14 -1
  54. data/ext/libcouchbase/src/n1ql/ixmgmt.cc +0 -3
  55. data/ext/libcouchbase/src/n1ql/n1ql.cc +22 -29
  56. data/ext/libcouchbase/src/n1ql/params.cc +46 -1
  57. data/ext/libcouchbase/src/newconfig.cc +4 -4
  58. data/ext/libcouchbase/src/operations/durability-seqno.cc +4 -0
  59. data/ext/libcouchbase/src/operations/durability.cc +3 -0
  60. data/ext/libcouchbase/src/operations/ping.cc +315 -0
  61. data/ext/libcouchbase/src/operations/stats.cc +10 -0
  62. data/ext/libcouchbase/src/operations/subdoc.cc +13 -1
  63. data/ext/libcouchbase/src/retrychk.cc +1 -0
  64. data/ext/libcouchbase/src/settings.c +2 -0
  65. data/ext/libcouchbase/src/settings.h +13 -7
  66. data/ext/libcouchbase/src/ssl/ssl_c.c +28 -2
  67. data/ext/libcouchbase/src/ssl/ssl_common.c +3 -0
  68. data/ext/libcouchbase/src/ssl/ssl_e.c +15 -1
  69. data/ext/libcouchbase/src/ssl/ssl_iot_common.h +3 -1
  70. data/ext/libcouchbase/src/timings.c +0 -1
  71. data/ext/libcouchbase/src/vbucket/vbucket.c +49 -1
  72. data/ext/libcouchbase/tests/iotests/mock-environment.cc +58 -40
  73. data/ext/libcouchbase/tests/iotests/mock-environment.h +23 -4
  74. data/ext/libcouchbase/tests/iotests/mock-unit-test.h +8 -8
  75. data/ext/libcouchbase/tests/iotests/t_behavior.cc +5 -5
  76. data/ext/libcouchbase/tests/iotests/t_durability.cc +50 -0
  77. data/ext/libcouchbase/tests/iotests/t_eerrs.cc +4 -2
  78. data/ext/libcouchbase/tests/iotests/t_errmap.cc +6 -3
  79. data/ext/libcouchbase/tests/iotests/t_lock.cc +5 -6
  80. data/ext/libcouchbase/tests/iotests/t_misc.cc +44 -0
  81. data/ext/libcouchbase/tests/iotests/t_serverops.cc +1 -0
  82. data/ext/libcouchbase/tests/iotests/t_subdoc.cc +28 -0
  83. data/ext/libcouchbase/tests/iotests/t_views.cc +22 -10
  84. data/ext/libcouchbase/tools/CMakeLists.txt +21 -1
  85. data/ext/libcouchbase/tools/cbc-handlers.h +23 -3
  86. data/ext/libcouchbase/tools/cbc-n1qlback.cc +1 -1
  87. data/ext/libcouchbase/tools/cbc-pillowfight.cc +126 -26
  88. data/ext/libcouchbase/tools/cbc-proxy.cc +403 -0
  89. data/ext/libcouchbase/tools/cbc-subdoc.cc +826 -0
  90. data/ext/libcouchbase/tools/cbc.cc +149 -37
  91. data/ext/libcouchbase/tools/common/options.h +5 -2
  92. data/ext/libcouchbase/tools/linenoise/linenoise.c +15 -15
  93. data/lib/libcouchbase.rb +4 -0
  94. data/lib/libcouchbase/bucket.rb +51 -0
  95. data/lib/libcouchbase/connection.rb +100 -13
  96. data/lib/libcouchbase/ext/libcouchbase.rb +40 -0
  97. data/lib/libcouchbase/ext/libcouchbase/cmdsubdoc.rb +13 -1
  98. data/lib/libcouchbase/ext/libcouchbase/enums.rb +2 -1
  99. data/lib/libcouchbase/ext/libcouchbase/sdspec.rb +5 -0
  100. data/lib/libcouchbase/subdoc_request.rb +129 -0
  101. data/lib/libcouchbase/version.rb +1 -1
  102. data/spec/bucket_spec.rb +15 -1
  103. data/spec/connection_spec.rb +1 -1
  104. data/spec/subdoc_spec.rb +192 -0
  105. metadata +13 -4
  106. data/ext/libcouchbase/.travis.yml +0 -19
File without changes
@@ -277,31 +277,31 @@ uint32_t cbsasl_hash(
277
277
  a += k[0] + (((uint32_t)k[1]) << 16);
278
278
  break;
279
279
  case 11:
280
- c += ((uint32_t)k8[10]) << 16; /* @fallthrough */
280
+ c += ((uint32_t)k8[10]) << 16; /* fall through */
281
281
  case 10:
282
- c += k[4]; /* @fallthrough@ */
282
+ c += k[4]; /* fall through */
283
283
  b += k[2] + (((uint32_t)k[3]) << 16);
284
284
  a += k[0] + (((uint32_t)k[1]) << 16);
285
285
  break;
286
286
  case 9 :
287
- c += k8[8]; /* @fallthrough */
287
+ c += k8[8]; /* fall through */
288
288
  case 8 :
289
289
  b += k[2] + (((uint32_t)k[3]) << 16);
290
290
  a += k[0] + (((uint32_t)k[1]) << 16);
291
291
  break;
292
292
  case 7 :
293
- b += ((uint32_t)k8[6]) << 16; /* @fallthrough */
293
+ b += ((uint32_t)k8[6]) << 16; /* fall through */
294
294
  case 6 :
295
295
  b += k[2];
296
296
  a += k[0] + (((uint32_t)k[1]) << 16);
297
297
  break;
298
298
  case 5 :
299
- b += k8[4]; /* @fallthrough */
299
+ b += k8[4]; /* fall through */
300
300
  case 4 :
301
301
  a += k[0] + (((uint32_t)k[1]) << 16);
302
302
  break;
303
303
  case 3 :
304
- a += ((uint32_t)k8[2]) << 16; /* @fallthrough */
304
+ a += ((uint32_t)k8[2]) << 16; /* fall through */
305
305
  case 2 :
306
306
  a += k[0];
307
307
  break;
@@ -337,27 +337,27 @@ uint32_t cbsasl_hash(
337
337
  /*-------------------------------- last block: affect all 32 bits of (c) */
338
338
  switch (length) { /* all the case statements fall through */
339
339
  case 12:
340
- c += ((uint32_t)k[11]) << 24;
340
+ c += ((uint32_t)k[11]) << 24; /* fall through */
341
341
  case 11:
342
- c += ((uint32_t)k[10]) << 16;
342
+ c += ((uint32_t)k[10]) << 16; /* fall through */
343
343
  case 10:
344
- c += ((uint32_t)k[9]) << 8;
344
+ c += ((uint32_t)k[9]) << 8; /* fall through */
345
345
  case 9 :
346
- c += k[8];
346
+ c += k[8]; /* fall through */
347
347
  case 8 :
348
- b += ((uint32_t)k[7]) << 24;
348
+ b += ((uint32_t)k[7]) << 24; /* fall through */
349
349
  case 7 :
350
- b += ((uint32_t)k[6]) << 16;
350
+ b += ((uint32_t)k[6]) << 16; /* fall through */
351
351
  case 6 :
352
- b += ((uint32_t)k[5]) << 8;
352
+ b += ((uint32_t)k[5]) << 8; /* fall through */
353
353
  case 5 :
354
- b += k[4];
354
+ b += k[4]; /* fall through */
355
355
  case 4 :
356
- a += ((uint32_t)k[3]) << 24;
356
+ a += ((uint32_t)k[3]) << 24; /* fall through */
357
357
  case 3 :
358
- a += ((uint32_t)k[2]) << 16;
358
+ a += ((uint32_t)k[2]) << 16; /* fall through */
359
359
  case 2 :
360
- a += ((uint32_t)k[1]) << 8;
360
+ a += ((uint32_t)k[1]) << 8; /* fall through */
361
361
  case 1 :
362
362
  a += k[0];
363
363
  break;
@@ -103,6 +103,66 @@ cliopts_list_clear(cliopts_list *l)
103
103
  l->nalloc = 0;
104
104
  }
105
105
 
106
+ static void
107
+ add_pair_list_value(const char *src, size_t nsrc, cliopts_pair_list *l)
108
+ {
109
+ char *key = NULL, *val = NULL;
110
+ char *sep = memchr(src, '=', nsrc);
111
+ if (sep == NULL) {
112
+ key = malloc(nsrc + 1);
113
+ memcpy(key, src, nsrc);
114
+ key[nsrc] = '\0';
115
+ val = malloc(1);
116
+ val[0] = '\0';
117
+ } else {
118
+ char *pp = sep;
119
+ size_t nkey = sep - src;
120
+ size_t nval = nsrc - nkey - 1;
121
+ for (; pp > src; pp--, nkey--) {
122
+ if (*pp != ' ' && *pp != '\t' && *pp != '\0') {
123
+ break;
124
+ }
125
+ }
126
+ key = malloc(nkey + 1);
127
+ memcpy(key, src, nkey);
128
+ key[nkey] = '\0';
129
+ val = malloc(nval + 1);
130
+ memcpy(val, sep + 1, nval);
131
+ val[nval] = '\0';
132
+ }
133
+
134
+ if (!l->nalloc) {
135
+ l->nalloc = 2;
136
+ l->keys = malloc(l->nalloc * sizeof(*l->keys));
137
+ l->values = malloc(l->nalloc * sizeof(*l->values));
138
+ } else {
139
+ l->nalloc *= 1.5;
140
+ l->keys = realloc(l->keys, sizeof(*l->keys) * l->nalloc);
141
+ l->values = realloc(l->values, sizeof(*l->values) * l->nalloc);
142
+ }
143
+
144
+ l->keys[l->nvalues] = key;
145
+ l->values[l->nvalues] = val;
146
+ l->nvalues++;
147
+ }
148
+
149
+ CLIOPTS_API
150
+ void
151
+ cliopts_pair_list_clear(cliopts_pair_list *l)
152
+ {
153
+ size_t ii;
154
+ for (ii = 0; ii < l->nvalues; ii++) {
155
+ free(l->keys[ii]);
156
+ free(l->values[ii]);
157
+ }
158
+ free(l->keys);
159
+ free(l->values);
160
+ l->keys = NULL;
161
+ l->values = NULL;
162
+ l->nvalues = 0;
163
+ l->nalloc = 0;
164
+ }
165
+
106
166
  /**
107
167
  * Various extraction/conversion functions for numerics
108
168
  */
@@ -230,6 +290,7 @@ parse_value(struct cliopts_priv *ctx,
230
290
  char *vp = malloc(vlen+1);
231
291
  vp[vlen] = 0;
232
292
  strcpy(vp, value);
293
+ free(*(char**)entry->dest);
233
294
  *(char**)entry->dest = vp;
234
295
  return WANT_OPTION;
235
296
  }
@@ -238,6 +299,10 @@ parse_value(struct cliopts_priv *ctx,
238
299
  add_list_value(value, vlen, (cliopts_list *)entry->dest);
239
300
  return WANT_OPTION;
240
301
  }
302
+ if (entry->ktype == CLIOPTS_ARGT_PAIR_LIST) {
303
+ add_pair_list_value(value, vlen, (cliopts_pair_list *)entry->dest);
304
+ return WANT_OPTION;
305
+ }
241
306
 
242
307
  if (entry->ktype == CLIOPTS_ARGT_FLOAT) {
243
308
  exfn = extract_float;
@@ -596,6 +661,17 @@ print_help(struct cliopts_priv *ctx, struct cliopts_extra_settings *settings)
596
661
  }
597
662
  break;
598
663
  }
664
+ case CLIOPTS_ARGT_PAIR_LIST: {
665
+ size_t ii;
666
+ cliopts_pair_list *l = (cliopts_pair_list *)cur->dest;
667
+ for (ii = 0; ii < l->nvalues; ii++) {
668
+ fprintf(stderr, "'%s=%s'", l->keys[ii], l->values[ii]);
669
+ if (ii != l->nvalues-1) {
670
+ fprintf(stderr, ", ");
671
+ }
672
+ }
673
+ break;
674
+ }
599
675
  case CLIOPTS_ARGT_FLOAT:
600
676
  fprintf(stderr, "%0.2f", *(float*)cur->dest);
601
677
  break;
@@ -47,7 +47,13 @@ typedef enum {
47
47
  * string. You can use this option type to build -Doption=value style
48
48
  * options which can be processed later on.
49
49
  */
50
- CLIOPTS_ARGT_LIST
50
+ CLIOPTS_ARGT_LIST,
51
+
52
+ /**
53
+ * Destination should be cliopts_pair_list. Argument type is assumed to be a
54
+ * string with '=' separator in form of KEY=VALUE.
55
+ */
56
+ CLIOPTS_ARGT_PAIR_LIST
51
57
  } cliopts_argtype_t;
52
58
 
53
59
  typedef struct {
@@ -134,6 +140,19 @@ typedef struct {
134
140
  size_t nalloc;
135
141
  } cliopts_list;
136
142
 
143
+ typedef struct {
144
+ /** Array of string pointers. Allocated via standard malloc functions */
145
+ char **keys;
146
+ /** Number of valid entries */
147
+ size_t nkeys;
148
+ /** Array of string pointers. Allocated via standard malloc functions */
149
+ char **values;
150
+ /** Number of valid entries */
151
+ size_t nvalues;
152
+ /** Number of entries allocated */
153
+ size_t nalloc;
154
+ } cliopts_pair_list;
155
+
137
156
  /**
138
157
  * Clear a list of its contents
139
158
  * @param l The list
@@ -142,6 +161,14 @@ CLIOPTS_API
142
161
  void
143
162
  cliopts_list_clear(cliopts_list *l);
144
163
 
164
+ /**
165
+ * Clear a pair list of its contents
166
+ * @param l The pair list
167
+ */
168
+ CLIOPTS_API
169
+ void
170
+ cliopts_pair_list_clear(cliopts_pair_list *l);
171
+
145
172
  /**
146
173
  * Parse options.
147
174
  *
@@ -265,9 +292,9 @@ public:
265
292
  TOption(TOption& other) {
266
293
  *(cliopts_entry*)this = *(cliopts_entry*) &other;
267
294
  innerVal = other.innerVal;
268
- dest = &innerVal;
269
295
  other.dest = NULL;
270
296
  doCopy(other);
297
+ dest = &innerVal;
271
298
  }
272
299
 
273
300
  ~TOption() {
@@ -292,6 +319,7 @@ public:
292
319
  * @return the option object, for method chaining.
293
320
  */
294
321
  inline Ttype& setDefault(const T& val) {
322
+ freeInnerVal();
295
323
  innerVal = val;
296
324
  return *this;
297
325
  }
@@ -349,16 +377,7 @@ protected:
349
377
  /** Called from within copy constructor */
350
378
  inline void doCopy(TOption&) {}
351
379
 
352
- inline void freeInnerVal() {
353
- switch (ktype) {
354
- case CLIOPTS_ARGT_LIST:
355
- cliopts_list_clear((cliopts_list *)&innerVal);
356
- break;
357
- default:
358
- /* nothing to do */
359
- break;
360
- }
361
- }
380
+ inline void freeInnerVal() {}
362
381
 
363
382
  /** Create the default value for the option */
364
383
  static inline Taccum createDefault() { return Taccum(); }
@@ -374,6 +393,11 @@ typedef TOption<std::vector<std::string>,
374
393
  cliopts_list,
375
394
  std::vector<std::string> > ListOption;
376
395
 
396
+ typedef TOption<std::vector<std::pair<std::string, std::string> >,
397
+ CLIOPTS_ARGT_PAIR_LIST,
398
+ cliopts_pair_list,
399
+ std::vector<std::pair<std::string, std::string> > > PairListOption;
400
+
377
401
  typedef TOption<bool,
378
402
  CLIOPTS_ARGT_NONE,
379
403
  int> BoolOption;
@@ -408,18 +432,24 @@ template<> inline std::string& StringOption::const_result() {
408
432
  template<> inline std::string StringOption::result() {
409
433
  return const_result();
410
434
  }
435
+ template<> inline void StringOption::freeInnerVal() {
436
+ free((void *)innerVal);
437
+ innerVal = NULL;
438
+ }
411
439
  template<> inline StringOption& StringOption::setDefault(const std::string& s) {
412
440
  priv = s;
413
- innerVal = priv.c_str();
441
+ freeInnerVal();
442
+ innerVal = strdup(priv.c_str());
414
443
  return *this;
415
444
  }
416
445
  template<> inline void StringOption::doCopy(StringOption& other) {
417
446
  priv = other.priv;
418
447
  if (other.innerVal == other.priv.c_str()) {
419
- innerVal = priv.c_str();
448
+ freeInnerVal();
449
+ innerVal = strdup(priv.c_str());
420
450
  }
421
451
  }
422
- template<> inline const char* StringOption::createDefault() { return ""; }
452
+ template<> inline const char* StringOption::createDefault() { return NULL; }
423
453
 
424
454
  // LIST ROUTINES
425
455
  template<> inline std::vector<std::string>& ListOption::const_result() {
@@ -433,6 +463,27 @@ template<> inline std::vector<std::string>& ListOption::const_result() {
433
463
  template<> inline std::vector<std::string> ListOption::result() {
434
464
  return const_result();
435
465
  }
466
+ template<> inline void ListOption::freeInnerVal() { cliopts_list_clear(&innerVal); }
467
+
468
+ struct PairListDtor {
469
+ static void call(void *arg) {
470
+ cliopts_pair_list_clear((cliopts_pair_list *)arg);
471
+ }
472
+ };
473
+
474
+ // PAIR LIST ROUTINES
475
+ template<> inline std::vector<std::pair<std::string, std::string> >& PairListOption::const_result() {
476
+ if (priv.empty()) {
477
+ for (size_t ii = 0; ii < innerVal.nvalues; ii++) {
478
+ priv.push_back(std::make_pair(innerVal.keys[ii], innerVal.values[ii]));
479
+ }
480
+ }
481
+ return priv;
482
+ }
483
+ template<> inline std::vector<std::pair<std::string, std::string> > PairListOption::result() {
484
+ return const_result();
485
+ }
486
+ template<> inline void PairListOption::freeInnerVal() { cliopts_pair_list_clear(&innerVal); }
436
487
 
437
488
  // BOOL ROUTINES
438
489
  template<> inline BoolOption& BoolOption::setDefault(const bool& b) {
@@ -149,7 +149,6 @@ static struct genhash_entry_t *genhash_find_entry(genhash_t *h,
149
149
  n = h->ops.hashfunc(k, klen) % h->size;
150
150
  lcb_assert(n < h->size);
151
151
 
152
- p = h->buckets[n];
153
152
  for (p = h->buckets[n]; p && !h->ops.hasheq(k, klen, p->key, p->nkey); p = p->next);
154
153
  return p;
155
154
  }
@@ -181,7 +180,7 @@ enum update_type genhash_update(genhash_t *h, const void *k, lcb_size_t klen,
181
180
  rv = MODIFICATION;
182
181
  } else {
183
182
  if (-1 == genhash_store(h, k, klen, v, vlen)) {
184
- rv = ALLOC_FAILURE;
183
+ return ALLOC_FAILURE;
185
184
  }
186
185
  rv = NEW;
187
186
  }
@@ -1275,7 +1275,8 @@ bool OurReader::readToken(Token& token) {
1275
1275
  token.type_ = tokenString;
1276
1276
  ok = readStringSingleQuote();
1277
1277
  break;
1278
- } // else continue
1278
+ }
1279
+ /* falls through */
1279
1280
  case '/':
1280
1281
  token.type_ = tokenComment;
1281
1282
  ok = readComment();
@@ -2351,12 +2352,12 @@ RuntimeError::RuntimeError(std::string const& msg)
2351
2352
  LogicError::LogicError(std::string const& msg)
2352
2353
  : Exception(msg)
2353
2354
  {}
2354
- void throwRuntimeError(std::string const& msg)
2355
+ void throwRuntimeError(std::string const& )
2355
2356
  {
2356
2357
  assert(false);
2357
2358
  // throw RuntimeError(msg);
2358
2359
  }
2359
- void throwLogicError(std::string const& msg)
2360
+ void throwLogicError(std::string const&)
2360
2361
  {
2361
2362
  assert(false);
2362
2363
  // throw LogicError(msg);
@@ -70,7 +70,7 @@ pthr_func(void *arg) {
70
70
  }
71
71
 
72
72
  #define NUM_WORKERS 20
73
- int main(void) {
73
+ int main(int argc, char *argv[]) {
74
74
  lcb_create_st options;
75
75
  pthread_t workers[NUM_WORKERS];
76
76
  Pool *pool;
@@ -79,7 +79,17 @@ int main(void) {
79
79
  // set up the options to represent your cluster (hostname etc)
80
80
  memset(&options, 0, sizeof options);
81
81
  options.version = 3;
82
- options.v.v3.connstr = "couchbase://localhost/default";
82
+ options.v.v3.connstr = "couchbase://localhost";
83
+ if (argc > 1) {
84
+ options.v.v3.connstr = argv[1];
85
+ }
86
+ if (argc > 2) {
87
+ options.v.v3.passwd = argv[2];
88
+ }
89
+ if (argc > 3) {
90
+ options.v.v3.username = argv[3];
91
+ }
92
+
83
93
  pool = new MyPool(options, 5);
84
94
 
85
95
  err = pool->connect();
@@ -15,6 +15,13 @@
15
15
  * limitations under the License.
16
16
  */
17
17
 
18
+ /**
19
+ * gcc -levent -lcouchbase main.c
20
+ *
21
+ * # perform STORE and 20 iterations of GET commands with interval 3 seconds
22
+ * ./a.out couchbase://localhost password Administrator 20 3
23
+ */
24
+
18
25
  #include <stdio.h>
19
26
  #include <stdlib.h>
20
27
  #include <string.h>
@@ -22,17 +29,29 @@
22
29
  #include <libcouchbase/api3.h>
23
30
  #include <event2/event.h>
24
31
 
25
- static void
26
- bootstrap_callback(lcb_t instance, lcb_error_t err)
32
+ const char key[] = "foo";
33
+ lcb_SIZE nkey = sizeof(key);
34
+
35
+ const char val[] = "{\"answer\":42}";
36
+ lcb_SIZE nval = sizeof(val);
37
+
38
+ int nreq = 1;
39
+ int nresp = 1;
40
+ int interval = 0;
41
+ struct event *timer = NULL;
42
+
43
+ static void bootstrap_callback(lcb_t instance, lcb_error_t err)
27
44
  {
28
- lcb_CMDSTORE cmd = { 0 };
45
+ lcb_CMDSTORE cmd = {0};
29
46
  if (err != LCB_SUCCESS) {
30
47
  fprintf(stderr, "ERROR: %s\n", lcb_strerror(instance, err));
31
48
  exit(EXIT_FAILURE);
32
49
  }
50
+ printf("successfully bootstrapped\n");
51
+ fflush(stdout);
33
52
  /* Since we've got our configuration, let's go ahead and store a value */
34
- LCB_CMD_SET_KEY(&cmd, "foo", 3);
35
- LCB_CMD_SET_VALUE(&cmd, "bar", 3);
53
+ LCB_CMD_SET_KEY(&cmd, key, nkey);
54
+ LCB_CMD_SET_VALUE(&cmd, val, nval);
36
55
  cmd.operation = LCB_SET;
37
56
  err = lcb_store3(instance, NULL, &cmd);
38
57
  if (err != LCB_SUCCESS) {
@@ -49,32 +68,68 @@ static void get_callback(lcb_t instance, int cbtype, const lcb_RESPBASE *rb)
49
68
  exit(EXIT_FAILURE);
50
69
  }
51
70
 
52
- fprintf(stdout, "I stored and retrieved the key 'foo'. Value: %.*s. Terminate program\n", (int)rg->nvalue, rg->value);
53
- event_base_loopbreak((void *)lcb_get_cookie(instance));
71
+ printf("%d. retrieved the key 'foo', value: %.*s\n", nresp, (int)rg->nvalue, rg->value);
72
+ fflush(stdout);
73
+ nresp--;
74
+ if (nresp == 0) {
75
+ printf("stopping the loop\n");
76
+ event_base_loopbreak((void *)lcb_get_cookie(instance));
77
+ }
54
78
  (void)cbtype;
55
79
  }
56
80
 
57
- static void store_callback(lcb_t instance, int cbtype, const lcb_RESPBASE *rb)
81
+ static void schedule_timer();
82
+
83
+ static void timer_callback(int fd, short event, void *arg)
58
84
  {
85
+ lcb_t instance = arg;
59
86
  lcb_error_t rc;
60
- lcb_CMDGET gcmd = { 0 };
87
+ lcb_CMDGET gcmd = {0};
61
88
 
62
- if (rb->rc != LCB_SUCCESS) {
63
- fprintf(stderr, "Failed to store key: %s\n", lcb_strerror(instance, rb->rc));
64
- exit(EXIT_FAILURE);
65
- }
66
-
67
- LCB_CMD_SET_KEY(&gcmd, rb->key, rb->nkey);
89
+ LCB_CMD_SET_KEY(&gcmd, key, nkey);
68
90
  rc = lcb_get3(instance, NULL, &gcmd);
69
91
  if (rc != LCB_SUCCESS) {
70
92
  fprintf(stderr, "Failed to schedule get request: %s\n", lcb_strerror(NULL, rc));
71
93
  exit(EXIT_FAILURE);
72
94
  }
95
+ (void)fd;
96
+ (void)event;
97
+ schedule_timer();
98
+ }
99
+
100
+ static void schedule_timer()
101
+ {
102
+ struct timeval tv;
103
+
104
+ if (!nreq) {
105
+ return;
106
+ }
107
+ tv.tv_sec = interval;
108
+ tv.tv_usec = 0;
109
+ evtimer_add(timer, &tv);
110
+ nreq--;
111
+ }
112
+
113
+ static void store_callback(lcb_t instance, int cbtype, const lcb_RESPBASE *rb)
114
+ {
115
+ if (rb->rc != LCB_SUCCESS) {
116
+ fprintf(stderr, "Failed to store key: %s\n", lcb_strerror(instance, rb->rc));
117
+ exit(EXIT_FAILURE);
118
+ }
119
+ printf("stored key 'foo'\n");
120
+ fflush(stdout);
121
+ {
122
+ struct event_base *evbase = (struct event_base *)lcb_get_cookie(instance);
123
+
124
+ printf("try to get value %d times with %dsec interval\n", nreq, interval);
125
+ timer = evtimer_new(evbase, timer_callback, instance);
126
+ schedule_timer();
127
+ }
128
+
73
129
  (void)cbtype;
74
130
  }
75
131
 
76
- static lcb_io_opt_t
77
- create_libevent_io_ops(struct event_base *evbase)
132
+ static lcb_io_opt_t create_libevent_io_ops(struct event_base *evbase)
78
133
  {
79
134
  struct lcb_create_io_ops_st ciops;
80
135
  lcb_io_opt_t ioops;
@@ -93,8 +148,7 @@ create_libevent_io_ops(struct event_base *evbase)
93
148
  return ioops;
94
149
  }
95
150
 
96
- static lcb_t
97
- create_libcouchbase_handle(lcb_io_opt_t ioops)
151
+ static lcb_t create_libcouchbase_handle(lcb_io_opt_t ioops, int argc, char **argv)
98
152
  {
99
153
  lcb_t instance;
100
154
  lcb_error_t error;
@@ -103,8 +157,17 @@ create_libcouchbase_handle(lcb_io_opt_t ioops)
103
157
  memset(&copts, 0, sizeof(copts));
104
158
 
105
159
  /* If NULL, will default to localhost */
106
- copts.v.v0.host = getenv("LCB_EVENT_SERVER");
107
- copts.v.v0.io = ioops;
160
+ copts.version = 3;
161
+ if (argc > 1) {
162
+ copts.v.v3.connstr = argv[1];
163
+ }
164
+ if (argc > 2) {
165
+ copts.v.v3.passwd = argv[2];
166
+ }
167
+ if (argc > 3) {
168
+ copts.v.v3.username = argv[3];
169
+ }
170
+ copts.v.v3.io = ioops;
108
171
  error = lcb_create(&instance, &copts);
109
172
 
110
173
  if (error != LCB_SUCCESS) {
@@ -128,12 +191,18 @@ create_libcouchbase_handle(lcb_io_opt_t ioops)
128
191
 
129
192
  /* This example shows how we can hook ourself into an external event loop.
130
193
  * You may find more information in the blogpost: http://goo.gl/fCTrX */
131
- int main(void)
194
+ int main(int argc, char **argv)
132
195
  {
133
196
  struct event_base *evbase = event_base_new();
134
197
  lcb_io_opt_t ioops = create_libevent_io_ops(evbase);
135
- lcb_t instance = create_libcouchbase_handle(ioops);
198
+ lcb_t instance = create_libcouchbase_handle(ioops, argc, argv);
136
199
 
200
+ if (argc > 4) {
201
+ nreq = nresp = atoi(argv[4]);
202
+ }
203
+ if (argc > 5) {
204
+ interval = atoi(argv[4]);
205
+ }
137
206
  /*Store the event base as the user cookie in our instance so that
138
207
  * we may terminate the program when we're done */
139
208
  lcb_set_cookie(instance, evbase);
@@ -142,7 +211,12 @@ int main(void)
142
211
  event_base_loop(evbase, 0);
143
212
 
144
213
  /* Cleanup */
145
- event_base_free(evbase);
146
214
  lcb_destroy(instance);
147
- exit(EXIT_SUCCESS);
215
+ if (timer) {
216
+ evtimer_del(timer);
217
+ }
218
+ lcb_destroy_io_ops(ioops);
219
+ event_base_free(evbase);
220
+
221
+ return EXIT_SUCCESS;
148
222
  }