libcouchbase 0.2.0 → 0.3.1

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 (129) hide show
  1. checksums.yaml +4 -4
  2. data/.travis.yml +1 -1
  3. data/README.md +1 -1
  4. data/ext/libcouchbase/CMakeLists.txt +8 -6
  5. data/ext/libcouchbase/README.markdown +2 -2
  6. data/ext/libcouchbase/RELEASE_NOTES.markdown +0 -86
  7. data/ext/libcouchbase/cmake/Modules/ConfigureDtrace.cmake +0 -11
  8. data/ext/libcouchbase/cmake/Modules/GenerateConfigDotH.cmake +0 -2
  9. data/ext/libcouchbase/cmake/Modules/GetLibcouchbaseFlags.cmake +1 -2
  10. data/ext/libcouchbase/cmake/Modules/GetVersionInfo.cmake +3 -3
  11. data/ext/libcouchbase/cmake/config-cmake.h.in +0 -2
  12. data/ext/libcouchbase/cmake/defs.mk.in +2 -0
  13. data/ext/libcouchbase/cmake/source_files.cmake +5 -21
  14. data/ext/libcouchbase/include/libcouchbase/auth.h +0 -10
  15. data/ext/libcouchbase/include/libcouchbase/cntl.h +1 -27
  16. data/ext/libcouchbase/include/libcouchbase/error.h +1 -15
  17. data/ext/libcouchbase/include/libcouchbase/n1ql.h +1 -13
  18. data/ext/libcouchbase/include/libcouchbase/plugins/io/bsdio-inl.c +1 -1
  19. data/ext/libcouchbase/include/libcouchbase/subdoc.h +0 -9
  20. data/ext/libcouchbase/include/libcouchbase/views.h +1 -7
  21. data/ext/libcouchbase/include/libcouchbase/visibility.h +0 -1
  22. data/ext/libcouchbase/include/memcached/protocol_binary.h +1131 -29
  23. data/ext/libcouchbase/include/memcached/vbucket.h +42 -0
  24. data/ext/libcouchbase/packaging/parse-git-describe.pl +1 -1
  25. data/ext/libcouchbase/plugins/io/libev/libev_io_opts.h +2 -3
  26. data/ext/libcouchbase/src/README.md +2 -0
  27. data/ext/libcouchbase/src/auth-priv.h +0 -1
  28. data/ext/libcouchbase/src/auth.cc +4 -10
  29. data/ext/libcouchbase/src/bootstrap.c +269 -0
  30. data/ext/libcouchbase/src/bootstrap.h +39 -50
  31. data/ext/libcouchbase/src/bucketconfig/bc_cccp.cc +117 -84
  32. data/ext/libcouchbase/src/bucketconfig/bc_file.c +347 -0
  33. data/ext/libcouchbase/src/bucketconfig/bc_http.c +630 -0
  34. data/ext/libcouchbase/src/bucketconfig/bc_http.h +25 -50
  35. data/ext/libcouchbase/src/bucketconfig/bc_mcraw.c +150 -0
  36. data/ext/libcouchbase/src/bucketconfig/clconfig.h +386 -407
  37. data/ext/libcouchbase/src/bucketconfig/confmon.c +474 -0
  38. data/ext/libcouchbase/src/cbft.cc +27 -22
  39. data/ext/libcouchbase/src/cntl.cc +19 -30
  40. data/ext/libcouchbase/src/connspec.cc +1 -48
  41. data/ext/libcouchbase/src/connspec.h +0 -27
  42. data/ext/libcouchbase/src/dump.cc +2 -2
  43. data/ext/libcouchbase/src/getconfig.cc +33 -7
  44. data/ext/libcouchbase/src/handler.cc +2 -0
  45. data/ext/libcouchbase/src/hostlist.cc +36 -0
  46. data/ext/libcouchbase/src/hostlist.h +62 -41
  47. data/ext/libcouchbase/src/http/http-priv.h +112 -125
  48. data/ext/libcouchbase/src/http/http.cc +30 -15
  49. data/ext/libcouchbase/src/http/http.h +34 -1
  50. data/ext/libcouchbase/src/http/http_io.cc +26 -22
  51. data/ext/libcouchbase/src/instance.cc +23 -94
  52. data/ext/libcouchbase/src/internal.h +26 -52
  53. data/ext/libcouchbase/src/jsparse/parser.cc +202 -146
  54. data/ext/libcouchbase/src/jsparse/parser.h +98 -91
  55. data/ext/libcouchbase/src/lcbht/lcbht.c +282 -0
  56. data/ext/libcouchbase/src/lcbht/lcbht.h +163 -174
  57. data/ext/libcouchbase/src/lcbio/connect.c +557 -0
  58. data/ext/libcouchbase/src/lcbio/connect.h +2 -9
  59. data/ext/libcouchbase/src/lcbio/ctx.c +1 -1
  60. data/ext/libcouchbase/src/lcbio/iotable.h +16 -61
  61. data/ext/libcouchbase/src/lcbio/ioutils.h +1 -1
  62. data/ext/libcouchbase/src/lcbio/manager.c +2 -2
  63. data/ext/libcouchbase/src/mc/mcreq.h +2 -9
  64. data/ext/libcouchbase/src/mcserver/mcserver.cc +34 -143
  65. data/ext/libcouchbase/src/mcserver/mcserver.h +12 -7
  66. data/ext/libcouchbase/src/mcserver/negotiate.cc +38 -132
  67. data/ext/libcouchbase/src/n1ql/ixmgmt.cc +2 -1
  68. data/ext/libcouchbase/src/n1ql/n1ql.cc +32 -56
  69. data/ext/libcouchbase/src/newconfig.cc +6 -6
  70. data/ext/libcouchbase/src/nodeinfo.cc +2 -2
  71. data/ext/libcouchbase/src/operations/{cbflush.cc → cbflush.c} +15 -7
  72. data/ext/libcouchbase/src/operations/{counter.cc → counter.c} +0 -0
  73. data/ext/libcouchbase/src/operations/durability.cc +26 -6
  74. data/ext/libcouchbase/src/operations/durability_internal.h +3 -6
  75. data/ext/libcouchbase/src/operations/{get.cc → get.c} +26 -24
  76. data/ext/libcouchbase/src/operations/{observe.cc → observe.c} +93 -68
  77. data/ext/libcouchbase/src/operations/{pktfwd.cc → pktfwd.c} +0 -0
  78. data/ext/libcouchbase/src/operations/{remove.cc → remove.c} +0 -0
  79. data/ext/libcouchbase/src/operations/stats.cc +8 -3
  80. data/ext/libcouchbase/src/operations/{store.cc → store.c} +32 -27
  81. data/ext/libcouchbase/src/operations/subdoc.cc +18 -38
  82. data/ext/libcouchbase/src/operations/{touch.cc → touch.c} +0 -0
  83. data/ext/libcouchbase/src/packetutils.c +37 -0
  84. data/ext/libcouchbase/src/packetutils.h +2 -2
  85. data/ext/libcouchbase/src/probes.d +1 -1
  86. data/ext/libcouchbase/src/{retrychk.cc → retrychk.c} +3 -2
  87. data/ext/libcouchbase/src/retryq.cc +4 -4
  88. data/ext/libcouchbase/src/settings.c +0 -3
  89. data/ext/libcouchbase/src/settings.h +0 -5
  90. data/ext/libcouchbase/src/simplestring.c +211 -0
  91. data/ext/libcouchbase/src/simplestring.h +228 -0
  92. data/ext/libcouchbase/src/ssl/ssl_c.c +0 -1
  93. data/ext/libcouchbase/src/ssl/ssl_common.c +0 -2
  94. data/ext/libcouchbase/src/ssl/ssl_e.c +1 -0
  95. data/ext/libcouchbase/src/ssobuf.h +82 -0
  96. data/ext/libcouchbase/src/trace.h +4 -4
  97. data/ext/libcouchbase/src/vbucket/vbucket.c +1 -0
  98. data/ext/libcouchbase/src/views/{docreq.cc → docreq.c} +54 -48
  99. data/ext/libcouchbase/src/views/docreq.h +30 -24
  100. data/ext/libcouchbase/src/views/viewreq.c +358 -0
  101. data/ext/libcouchbase/src/views/viewreq.h +13 -43
  102. data/ext/libcouchbase/tests/basic/t_connstr.cc +50 -89
  103. data/ext/libcouchbase/tests/basic/t_host.cc +75 -67
  104. data/ext/libcouchbase/tests/basic/t_jsparse.cc +78 -27
  105. data/ext/libcouchbase/tests/basic/t_string.cc +112 -0
  106. data/ext/libcouchbase/tests/htparse/t_basic.cc +78 -58
  107. data/ext/libcouchbase/tests/iotests/mock-environment.h +1 -2
  108. data/ext/libcouchbase/tests/iotests/t_confmon.cc +114 -96
  109. data/ext/libcouchbase/tests/mc/t_alloc.cc +9 -9
  110. data/ext/libcouchbase/tools/cbc-pillowfight.cc +1 -1
  111. data/lib/libcouchbase/ext/tasks.rb +6 -2
  112. data/lib/libcouchbase/query_view.rb +1 -1
  113. data/lib/libcouchbase/results_fiber.rb +6 -6
  114. data/lib/libcouchbase/version.rb +1 -1
  115. metadata +26 -26
  116. data/ext/libcouchbase/src/bootstrap.cc +0 -216
  117. data/ext/libcouchbase/src/bucketconfig/bc_file.cc +0 -281
  118. data/ext/libcouchbase/src/bucketconfig/bc_http.cc +0 -528
  119. data/ext/libcouchbase/src/bucketconfig/bc_mcraw.cc +0 -115
  120. data/ext/libcouchbase/src/bucketconfig/confmon.cc +0 -378
  121. data/ext/libcouchbase/src/dns-srv.cc +0 -142
  122. data/ext/libcouchbase/src/errmap.cc +0 -107
  123. data/ext/libcouchbase/src/errmap.h +0 -113
  124. data/ext/libcouchbase/src/lcbht/lcbht.cc +0 -177
  125. data/ext/libcouchbase/src/lcbio/connect.cc +0 -562
  126. data/ext/libcouchbase/src/lcbio/timer-cxx.h +0 -87
  127. data/ext/libcouchbase/src/mctx-helper.h +0 -51
  128. data/ext/libcouchbase/src/views/viewreq.cc +0 -318
  129. data/ext/libcouchbase/tests/iotests/t_errmap.cc +0 -97
@@ -24,54 +24,36 @@
24
24
  #include "internal.h"
25
25
  #include "clconfig.h"
26
26
  #include "packetutils.h"
27
+ #include "simplestring.h"
27
28
  #include <mcserver/negotiate.h>
28
29
  #include <lcbio/lcbio.h>
29
- #include <lcbio/timer-cxx.h>
30
+ #include <lcbio/timer-ng.h>
30
31
  #include <lcbio/ssl.h>
31
32
  #include "ctx-log-inl.h"
32
33
  #define LOGARGS(cccp, lvl) cccp->parent->settings, "cccp", LCB_LOG_##lvl, __FILE__, __LINE__
33
34
  #define LOGFMT "<%s:%s> "
34
35
  #define LOGID(cccp) get_ctx_host(cccp->ioctx), get_ctx_port(cccp->ioctx)
35
36
 
36
- struct CccpCookie;
37
+ #define PROVIDER_SETTING_T(fld) PROVIDER_SETTING(this, fld)
37
38
 
38
- using namespace lcb::clconfig;
39
+ struct CccpCookie;
39
40
 
40
- struct CccpProvider : public Provider {
41
- CccpProvider(Confmon *);
41
+ struct CccpProvider : public clconfig_provider {
42
+ CccpProvider(lcb_confmon *);
42
43
  ~CccpProvider();
43
44
 
44
45
  void release_socket(bool can_reuse);
45
46
  lcb_error_t schedule_next_request(lcb_error_t why, bool can_rollover);
46
47
  lcb_error_t mcio_error(lcb_error_t why);
47
- void on_timeout() { mcio_error(LCB_ETIMEDOUT); }
48
48
  lcb_error_t update(const char *host, const char* data);
49
49
  void request_config();
50
+ void on_config_updated(lcbvb_CONFIG *vbc);
50
51
  void on_io_read();
51
52
 
52
- bool pause(); // Override
53
- void configure_nodes(const lcb::Hostlist&); // Override
54
- void config_updated(lcbvb_CONFIG *); // Override;
55
- void dump(FILE*) const; // Override
56
- lcb_error_t refresh(); // Override
57
-
58
- ConfigInfo *get_cached() /* Override */ {
59
- return config;
60
- }
61
-
62
- const lcb::Hostlist* get_nodes() const /* Override */ {
63
- return nodes;
64
- }
65
-
66
- void enable(void *arg) {
67
- instance = reinterpret_cast<lcb_t>(arg);
68
- Provider::enable();
69
- }
70
-
71
53
  lcb::Hostlist *nodes;
72
- ConfigInfo *config;
54
+ clconfig_info *config;
73
55
  bool server_active;
74
- lcb::io::Timer<CccpProvider, &CccpProvider::on_timeout> timer;
56
+ lcbio_pTIMER timer;
75
57
  lcb_t instance;
76
58
  lcbio_CONNREQ creq;
77
59
  lcbio_CTX *ioctx;
@@ -124,19 +106,19 @@ CccpProvider::schedule_next_request(lcb_error_t err, bool can_rollover)
124
106
  lcb::Server *server;
125
107
  lcb_host_t *next_host = nodes->next(can_rollover);
126
108
  if (!next_host) {
127
- timer.cancel();
128
- parent->provider_failed(this, err);
109
+ lcbio_timer_disarm(timer);
110
+ lcb_confmon_provider_failed(this, err);
129
111
  server_active = false;
130
112
  return err;
131
113
  }
132
114
 
133
- server = instance->find_server(*next_host);
115
+ server = lcb_find_server_by_host(instance, next_host);
134
116
  if (server) {
135
117
  CccpCookie *cookie = new CccpCookie(this);
136
118
  cmdcookie = cookie;
137
119
  lcb_log(LOGARGS(this, INFO), "Re-Issuing CCCP Command on server struct %p (%s:%s)", (void*)server, next_host->host, next_host->port);
138
- timer.rearm(settings().config_node_timeout);
139
- instance->request_config(cookie, server);
120
+ lcbio_timer_rearm(timer, PROVIDER_SETTING_T(config_node_timeout));
121
+ return lcb_getconfig(instance, cookie, server);
140
122
 
141
123
  } else {
142
124
  lcbio_pMGRREQ preq;
@@ -144,7 +126,7 @@ CccpProvider::schedule_next_request(lcb_error_t err, bool can_rollover)
144
126
  lcb_log(LOGARGS(this, INFO), "Requesting connection to node %s:%s for CCCP configuration", next_host->host, next_host->port);
145
127
  preq = lcbio_mgr_get(
146
128
  instance->memd_sockpool, next_host,
147
- settings().config_node_timeout,
129
+ PROVIDER_SETTING_T(config_node_timeout),
148
130
  on_connected, this);
149
131
  LCBIO_CONNREQ_MKPOOLED(&creq, preq);
150
132
  }
@@ -157,16 +139,32 @@ lcb_error_t
157
139
  CccpProvider::mcio_error(lcb_error_t err)
158
140
  {
159
141
  if (err != LCB_NOT_SUPPORTED && err != LCB_UNKNOWN_COMMAND) {
160
- lcb_log(LOGARGS(this, ERR), LOGFMT "Could not get configuration: %s", LOGID(this), lcb_strerror_short(err));
142
+ lcb_log(LOGARGS(this, ERR), LOGFMT "Got I/O Error=0x%x", LOGID(this), err);
161
143
  }
162
144
 
163
145
  release_socket(err == LCB_NOT_SUPPORTED);
164
146
  return schedule_next_request(err, false);
165
147
  }
166
148
 
149
+ static void socket_timeout(void *arg) {
150
+ reinterpret_cast<CccpProvider*>(arg)->mcio_error(LCB_ETIMEDOUT);
151
+ }
152
+
153
+ void lcb_clconfig_cccp_enable(clconfig_provider *pb, lcb_t instance)
154
+ {
155
+ CccpProvider *cccp = static_cast<CccpProvider*>(pb);
156
+ lcb_assert(pb->type == LCB_CLCONFIG_CCCP);
157
+ cccp->instance = instance;
158
+ pb->enabled = true;
159
+ }
160
+
161
+ static hostlist_t get_nodes(const clconfig_provider *pb) {
162
+ return static_cast<const CccpProvider*>(pb)->nodes;
163
+ }
164
+
167
165
  /** Update the configuration from a server. */
168
166
  lcb_error_t
169
- lcb::clconfig::cccp_update(Provider *provider, const char *host, const char *data) {
167
+ lcb_cccp_update(clconfig_provider *provider, const char *host, const char *data) {
170
168
  return static_cast<CccpProvider*>(provider)->update(host, data);
171
169
  }
172
170
 
@@ -176,7 +174,7 @@ CccpProvider::update(const char *host, const char *data)
176
174
  /** TODO: replace this with lcbvb_ names */
177
175
  lcbvb_CONFIG* vbc;
178
176
  int rv;
179
- ConfigInfo *new_config;
177
+ clconfig_info *new_config;
180
178
  vbc = lcbvb_create();
181
179
 
182
180
  if (!vbc) {
@@ -192,7 +190,7 @@ CccpProvider::update(const char *host, const char *data)
192
190
  }
193
191
 
194
192
  lcbvb_replace_host(vbc, host);
195
- new_config = ConfigInfo::create(vbc, CLCONFIG_CCCP);
193
+ new_config = lcb_clconfig_create(vbc, LCB_CLCONFIG_CCCP);
196
194
 
197
195
  if (!new_config) {
198
196
  lcbvb_destroy(vbc);
@@ -200,24 +198,25 @@ CccpProvider::update(const char *host, const char *data)
200
198
  }
201
199
 
202
200
  if (config) {
203
- config->decref();
201
+ lcb_clconfig_decref(config);
204
202
  }
205
203
 
206
204
  /** TODO: Figure out the comparison vector */
205
+ new_config->cmpclock = gethrtime();
207
206
  config = new_config;
208
- parent->provider_got_config(this, new_config);
207
+ lcb_confmon_provider_success(this, new_config);
209
208
  return LCB_SUCCESS;
210
209
  }
211
210
 
212
- void lcb::clconfig::cccp_update(
213
- const void *cookie, lcb_error_t err,
214
- const void *bytes, size_t nbytes, const lcb_host_t *origin)
211
+ void lcb_cccp_update2(const void *cookie, lcb_error_t err,
212
+ const void *bytes, lcb_size_t nbytes,
213
+ const lcb_host_t *origin)
215
214
  {
216
215
  CccpCookie *ck = reinterpret_cast<CccpCookie*>(const_cast<void*>(cookie));
217
216
  CccpProvider *cccp = ck->parent;
218
217
 
219
218
  if (ck == cccp->cmdcookie) {
220
- cccp->timer.cancel();
219
+ lcbio_timer_disarm(cccp->timer);
221
220
  cccp->cmdcookie = NULL;
222
221
  }
223
222
 
@@ -264,53 +263,70 @@ on_connected(lcbio_SOCKET *sock, void *data, lcb_error_t err, lcbio_OSERR)
264
263
  cccp->request_config();
265
264
  }
266
265
 
267
- lcb_error_t CccpProvider::refresh() {
268
- if (creq.u.p_generic || server_active || cmdcookie) {
266
+ static lcb_error_t cccp_get(clconfig_provider *pb)
267
+ {
268
+ CccpProvider *cccp = static_cast<CccpProvider *>(pb);
269
+ if (cccp->creq.u.p_generic || cccp->server_active || cccp->cmdcookie) {
269
270
  return LCB_BUSY;
270
271
  }
271
272
 
272
- return schedule_next_request(LCB_SUCCESS, true);
273
+ return cccp->schedule_next_request(LCB_SUCCESS, true);
273
274
  }
274
275
 
275
- bool
276
- CccpProvider::pause()
276
+ static clconfig_info *cccp_get_cached(clconfig_provider *pb) {
277
+ return static_cast<CccpProvider *>(pb)->config;
278
+ }
279
+
280
+ static lcb_error_t cccp_pause(clconfig_provider *pb)
277
281
  {
278
- if (!server_active) {
279
- return true;
282
+ CccpProvider *cccp = static_cast<CccpProvider *>(pb);
283
+ if (!cccp->server_active) {
284
+ return LCB_SUCCESS;
280
285
  }
281
286
 
282
- server_active = 0;
283
- release_socket(false);
284
- timer.cancel();
285
- return true;
287
+ cccp->server_active = 0;
288
+ cccp->release_socket(false);
289
+ lcbio_timer_disarm(cccp->timer);
290
+ return LCB_SUCCESS;
291
+ }
292
+
293
+ static void cccp_cleanup(clconfig_provider *pb) {
294
+ delete static_cast<CccpProvider*>(pb);
286
295
  }
287
296
 
288
297
  CccpProvider::~CccpProvider() {
289
298
  release_socket(false);
290
299
 
291
300
  if (config) {
292
- config->decref();
301
+ lcb_clconfig_decref(config);
293
302
  }
294
303
  if (nodes) {
295
304
  delete nodes;
296
305
  }
297
- timer.release();
306
+ if (timer) {
307
+ lcbio_timer_destroy(timer);
308
+ }
298
309
  if (cmdcookie) {
299
310
  cmdcookie->ignore_errors = 1;
300
311
  }
301
312
  }
302
313
 
303
- void
304
- CccpProvider::configure_nodes(const lcb::Hostlist& nodes_)
314
+ static void
315
+ configure_nodes(clconfig_provider *pb, const hostlist_t nodes)
305
316
  {
306
- nodes->assign(nodes_);
307
- if (parent->settings->randomize_bootstrap_nodes) {
308
- nodes->randomize();
317
+ CccpProvider *cccp = static_cast<CccpProvider *>(pb);
318
+ cccp->nodes->assign(*nodes);
319
+ if (PROVIDER_SETTING(pb, randomize_bootstrap_nodes)) {
320
+ cccp->nodes->randomize();
309
321
  }
310
322
  }
311
323
 
324
+ static void config_updated(clconfig_provider *provider, lcbvb_CONFIG* vbc) {
325
+ static_cast<CccpProvider*>(provider)->on_config_updated(vbc);
326
+ }
327
+
312
328
  void
313
- CccpProvider::config_updated(lcbvb_CONFIG *vbc)
329
+ CccpProvider::on_config_updated(lcbvb_CONFIG *vbc)
314
330
  {
315
331
  lcbvb_SVCMODE mode;
316
332
  if (LCBVB_NSERVERS(vbc) < 1) {
@@ -318,7 +334,7 @@ CccpProvider::config_updated(lcbvb_CONFIG *vbc)
318
334
  }
319
335
 
320
336
  nodes->clear();
321
- if (settings().sslopts & LCB_SSL_ENABLED) {
337
+ if (PROVIDER_SETTING_T(sslopts) & LCB_SSL_ENABLED) {
322
338
  mode = LCBVB_SVCMODE_SSL;
323
339
  } else {
324
340
  mode = LCBVB_SVCMODE_PLAIN;
@@ -333,7 +349,7 @@ CccpProvider::config_updated(lcbvb_CONFIG *vbc)
333
349
  nodes->add(mcaddr, LCB_CONFIG_MCD_PORT);
334
350
  }
335
351
 
336
- if (settings().randomize_bootstrap_nodes) {
352
+ if (PROVIDER_SETTING_T(randomize_bootstrap_nodes)) {
337
353
  nodes->randomize();
338
354
  }
339
355
  }
@@ -395,7 +411,7 @@ CccpProvider::on_io_read()
395
411
  lcb_error_t err = update(hoststr.c_str(), jsonstr.c_str());
396
412
 
397
413
  if (err == LCB_SUCCESS) {
398
- timer.cancel();
414
+ lcbio_timer_disarm(timer);
399
415
  server_active = false;
400
416
  } else {
401
417
  schedule_next_request(LCB_PROTOCOL_ERROR, 0);
@@ -411,45 +427,62 @@ void CccpProvider::request_config()
411
427
  lcbio_ctx_put(ioctx, req.data(), req.size());
412
428
  lcbio_ctx_rwant(ioctx, 24);
413
429
  lcbio_ctx_schedule(ioctx);
414
- timer.rearm(settings().config_node_timeout);
430
+ lcbio_timer_rearm(timer, PROVIDER_SETTING(this, config_node_timeout));
415
431
  }
416
432
 
417
- void CccpProvider::dump(FILE *fp) const {
418
- if (!enabled) {
433
+ static void do_dump(clconfig_provider *pb, FILE *fp)
434
+ {
435
+ CccpProvider *cccp = (CccpProvider *)pb;
436
+
437
+ if (!cccp->enabled) {
419
438
  return;
420
439
  }
421
440
 
422
441
  fprintf(fp, "## BEGIN CCCP PROVIDER DUMP ##\n");
423
- fprintf(fp, "TIMER ACTIVE: %s\n", timer.is_armed() ? "YES" : "NO");
424
- fprintf(fp, "PIPELINE RESPONSE COOKIE: %p\n", (void*)cmdcookie);
425
- if (ioctx) {
442
+ fprintf(fp, "TIMER ACTIVE: %s\n", lcbio_timer_armed(cccp->timer) ? "YES" : "NO");
443
+ fprintf(fp, "PIPELINE RESPONSE COOKIE: %p\n", (void*)cccp->cmdcookie);
444
+ if (cccp->ioctx) {
426
445
  fprintf(fp, "CCCP Owns connection:\n");
427
- lcbio_ctx_dump(ioctx, fp);
428
- } else if (creq.u.p_generic) {
446
+ lcbio_ctx_dump(cccp->ioctx, fp);
447
+ } else if (cccp->creq.u.p_generic) {
429
448
  fprintf(fp, "CCCP Is connecting\n");
430
449
  } else {
431
450
  fprintf(fp, "CCCP does not have a dedicated connection\n");
432
451
  }
433
452
 
434
- for (size_t ii = 0; ii < nodes->size(); ii++) {
435
- const lcb_host_t &curhost = (*nodes)[ii];
453
+ for (size_t ii = 0; ii < cccp->nodes->size(); ii++) {
454
+ const lcb_host_t &curhost = (*cccp->nodes)[ii];
436
455
  fprintf(fp, "CCCP NODE: %s:%s\n", curhost.host, curhost.port);
437
456
  }
438
457
  fprintf(fp, "## END CCCP PROVIDER DUMP ##\n");
439
458
  }
440
459
 
441
- CccpProvider::CccpProvider(Confmon *mon)
442
- : Provider(mon, CLCONFIG_CCCP),
443
- nodes(new lcb::Hostlist()),
460
+ clconfig_provider * lcb_clconfig_create_cccp(lcb_confmon *mon)
461
+ {
462
+ return new CccpProvider(mon);
463
+ }
464
+
465
+ CccpProvider::CccpProvider(lcb_confmon *mon)
466
+ : nodes(new lcb::Hostlist()),
444
467
  config(NULL),
445
468
  server_active(false),
446
- timer(mon->iot, this),
469
+ timer(NULL),
447
470
  instance(NULL),
448
471
  ioctx(NULL),
449
- cmdcookie(NULL) {
472
+ cmdcookie(NULL)
473
+ {
474
+ clconfig_provider::type = LCB_CLCONFIG_CCCP;
475
+ clconfig_provider::refresh = cccp_get;
476
+ clconfig_provider::get_cached = cccp_get_cached;
477
+ clconfig_provider::pause = cccp_pause;
478
+ clconfig_provider::shutdown = cccp_cleanup;
479
+ clconfig_provider::config_updated = ::config_updated;
480
+ clconfig_provider::configure_nodes = ::configure_nodes;
481
+ clconfig_provider::get_nodes = ::get_nodes;
482
+ clconfig_provider::dump = do_dump;
483
+ clconfig_provider::parent = mon;
484
+ clconfig_provider::enabled = 0;
485
+
486
+ timer = lcbio_timer_new(mon->iot, this, socket_timeout);
450
487
  std::memset(&creq, 0, sizeof creq);
451
488
  }
452
-
453
- Provider* lcb::clconfig::new_cccp_provider(Confmon *mon) {
454
- return new CccpProvider(mon);
455
- }
@@ -0,0 +1,347 @@
1
+ /* -*- Mode: C; tab-width: 4; c-basic-offset: 4; indent-tabs-mode: nil -*- */
2
+ /*
3
+ * Copyright 2013 Couchbase, Inc.
4
+ *
5
+ * Licensed under the Apache License, Version 2.0 (the "License");
6
+ * you may not use this file except in compliance with the License.
7
+ * You may obtain a copy of the License at
8
+ *
9
+ * http://www.apache.org/licenses/LICENSE-2.0
10
+ *
11
+ * Unless required by applicable law or agreed to in writing, software
12
+ * distributed under the License is distributed on an "AS IS" BASIS,
13
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14
+ * See the License for the specific language governing permissions and
15
+ * limitations under the License.
16
+ */
17
+
18
+ #include "internal.h"
19
+ #include "clconfig.h"
20
+ #include "simplestring.h"
21
+ #include <lcbio/lcbio.h>
22
+ #include <lcbio/timer-ng.h>
23
+
24
+ #define CONFIG_CACHE_MAGIC "{{{fb85b563d0a8f65fa8d3d58f1b3a0708}}}"
25
+
26
+ #define LOGARGS(pb, lvl) pb->base.parent->settings, "bc_file", LCB_LOG_##lvl, __FILE__, __LINE__
27
+ #define LOGFMT "(cache=%s) "
28
+ #define LOGID(fb) fb->filename
29
+
30
+ typedef struct {
31
+ clconfig_provider base;
32
+ char *filename;
33
+ clconfig_info *config;
34
+ time_t last_mtime;
35
+ int last_errno;
36
+ int ro_mode; /* Whether the config cache should _not_ overwrite the file */
37
+ lcbio_pTIMER timer;
38
+ clconfig_listener listener;
39
+ } file_provider;
40
+
41
+ static int load_cache(file_provider *provider)
42
+ {
43
+ lcb_string str;
44
+ char line[1024];
45
+ lcb_ssize_t nr;
46
+ int fail;
47
+ FILE *fp = NULL;
48
+ lcbvb_CONFIG *config = NULL;
49
+ char *end;
50
+ struct stat st;
51
+ int status = -1;
52
+
53
+ lcb_string_init(&str);
54
+
55
+ if (provider->filename == NULL) {
56
+ return -1;
57
+ }
58
+
59
+ fp = fopen(provider->filename, "r");
60
+ if (fp == NULL) {
61
+ int save_errno = errno;
62
+ lcb_log(LOGARGS(provider, ERROR), LOGFMT "Couldn't open for reading: %s", LOGID(provider), strerror(save_errno));
63
+ return -1;
64
+ }
65
+
66
+ if (fstat(fileno(fp), &st)) {
67
+ provider->last_errno = errno;
68
+ goto GT_DONE;
69
+ }
70
+
71
+ if (provider->last_mtime == st.st_mtime) {
72
+ lcb_log(LOGARGS(provider, WARN), LOGFMT "Modification time too old", LOGID(provider));
73
+ goto GT_DONE;
74
+ }
75
+
76
+ config = lcbvb_create();
77
+ if (config == NULL) {
78
+ goto GT_DONE;
79
+ }
80
+
81
+ lcb_string_init(&str);
82
+
83
+ while ((nr = fread(line, 1, sizeof(line), fp)) > 0) {
84
+ if (lcb_string_append(&str, line, nr)) {
85
+ goto GT_DONE;
86
+ }
87
+ }
88
+
89
+ if (ferror(fp)) {
90
+ goto GT_DONE;
91
+ }
92
+
93
+ fclose(fp);
94
+ fp = NULL;
95
+
96
+ if (!str.nused) {
97
+ status = -1;
98
+ goto GT_DONE;
99
+ }
100
+
101
+ end = strstr(str.base, CONFIG_CACHE_MAGIC);
102
+ if (end == NULL) {
103
+ lcb_log(LOGARGS(provider, ERROR), LOGFMT "Couldn't find magic", LOGID(provider));
104
+ if (!provider->ro_mode) {
105
+ remove(provider->filename);
106
+ }
107
+ status = -1;
108
+ goto GT_DONE;
109
+ }
110
+
111
+ fail = lcbvb_load_json(config, str.base);
112
+ if (fail) {
113
+ status = -1;
114
+ lcb_log(LOGARGS(provider, ERROR), LOGFMT "Couldn't parse configuration", LOGID(provider));
115
+ lcb_log_badconfig(LOGARGS(provider, ERROR), config, str.base);
116
+ if (!provider->ro_mode) {
117
+ remove(provider->filename);
118
+ }
119
+ goto GT_DONE;
120
+ }
121
+
122
+ if (lcbvb_get_distmode(config) != LCBVB_DIST_VBUCKET) {
123
+ status = -1;
124
+ lcb_log(LOGARGS(provider, ERROR), LOGFMT "Not applying cached memcached config", LOGID(provider));
125
+ goto GT_DONE;
126
+ }
127
+
128
+ if (strcmp(config->bname, PROVIDER_SETTING(&provider->base, bucket)) != 0) {
129
+ status = -1;
130
+ lcb_log(LOGARGS(provider, ERROR), LOGFMT "Bucket name in file is different from the one requested", LOGID(provider));
131
+ }
132
+
133
+ if (provider->config) {
134
+ lcb_clconfig_decref(provider->config);
135
+ }
136
+
137
+ provider->config = lcb_clconfig_create(config, LCB_CLCONFIG_FILE);
138
+ provider->config->cmpclock = gethrtime();
139
+ provider->config->origin = provider->base.type;
140
+ provider->last_mtime = st.st_mtime;
141
+ status = 0;
142
+ config = NULL;
143
+
144
+ GT_DONE:
145
+ if (fp != NULL) {
146
+ fclose(fp);
147
+ }
148
+
149
+ if (config != NULL) {
150
+ lcbvb_destroy(config);
151
+ }
152
+
153
+ lcb_string_release(&str);
154
+ return status;
155
+ }
156
+
157
+ static void
158
+ write_to_file(file_provider *provider, lcbvb_CONFIG *cfg)
159
+ {
160
+ FILE *fp;
161
+
162
+ if (provider->filename == NULL || provider->ro_mode) {
163
+ return;
164
+ }
165
+
166
+ fp = fopen(provider->filename, "w");
167
+ if (fp) {
168
+ char *json = lcbvb_save_json(cfg);
169
+ lcb_log(LOGARGS(provider, INFO), LOGFMT "Writing configuration to file", LOGID(provider));
170
+ fprintf(fp, "%s%s", json, CONFIG_CACHE_MAGIC);
171
+ fclose(fp);
172
+ free(json);
173
+ } else {
174
+ int save_errno = errno;
175
+ lcb_log(LOGARGS(provider, ERROR), LOGFMT "Couldn't open file for writing: %s", LOGID(provider), strerror(save_errno));
176
+ }
177
+ }
178
+
179
+ static clconfig_info * get_cached(clconfig_provider *pb)
180
+ {
181
+ file_provider *provider = (file_provider *)pb;
182
+ if (!provider->filename) {
183
+ return NULL;
184
+ }
185
+
186
+ return provider->config;
187
+ }
188
+
189
+ static void async_callback(void *cookie)
190
+ {
191
+ time_t last_mtime;
192
+ file_provider *provider = (file_provider *)cookie;
193
+ last_mtime = provider->last_mtime;
194
+ if (load_cache(provider) == 0) {
195
+ if (last_mtime != provider->last_mtime) {
196
+ lcb_confmon_provider_success(&provider->base, provider->config);
197
+ return;
198
+ }
199
+ }
200
+
201
+ lcb_confmon_provider_failed(&provider->base, LCB_ERROR);
202
+ }
203
+
204
+ static lcb_error_t refresh_file(clconfig_provider *pb)
205
+ {
206
+ file_provider *provider = (file_provider *)pb;
207
+ if (lcbio_timer_armed(provider->timer)) {
208
+ return LCB_SUCCESS;
209
+ }
210
+
211
+ lcbio_async_signal(provider->timer);
212
+ return LCB_SUCCESS;
213
+ }
214
+
215
+ static lcb_error_t pause_file(clconfig_provider *pb)
216
+ {
217
+ (void)pb;
218
+ return LCB_SUCCESS;
219
+ }
220
+
221
+ static void shutdown_file(clconfig_provider *pb)
222
+ {
223
+ file_provider *provider = (file_provider *)pb;
224
+ free(provider->filename);
225
+ if (provider->timer) {
226
+ lcbio_timer_destroy(provider->timer);
227
+ }
228
+ if (provider->config) {
229
+ lcb_clconfig_decref(provider->config);
230
+ }
231
+ free(provider);
232
+ }
233
+
234
+ static void config_listener(clconfig_listener *lsn, clconfig_event_t event,
235
+ clconfig_info *info)
236
+ {
237
+ file_provider *provider;
238
+
239
+ if (event != CLCONFIG_EVENT_GOT_NEW_CONFIG) {
240
+ return;
241
+ }
242
+
243
+ provider = (file_provider *) (void*)(((char *)lsn) - offsetof(file_provider, listener));
244
+ if (!provider->base.enabled) {
245
+ return;
246
+ }
247
+
248
+ if (info->origin == LCB_CLCONFIG_PHONY || info->origin == LCB_CLCONFIG_FILE) {
249
+ lcb_log(LOGARGS(provider, TRACE), "Not writing configuration originating from PHONY or FILE to cache");
250
+ return;
251
+ }
252
+
253
+ write_to_file(provider, info->vbc);
254
+ }
255
+
256
+ static void
257
+ do_file_dump(clconfig_provider *pb, FILE *fp)
258
+ {
259
+ file_provider *pr = (file_provider *)pb;
260
+
261
+ fprintf(fp, "## BEGIN FILE PROVIEDER DUMP ##\n");
262
+ if (pr->filename) {
263
+ fprintf(fp, "FILENAME: %s\n", pr->filename);
264
+ }
265
+ fprintf(fp, "LAST SYSTEM ERRNO: %d\n", pr->last_errno);
266
+ fprintf(fp, "LAST MTIME: %lu\n", (unsigned long)pr->last_mtime);
267
+ fprintf(fp, "## END FILE PROVIDER DUMP ##\n");
268
+
269
+ }
270
+
271
+ clconfig_provider * lcb_clconfig_create_file(lcb_confmon *parent)
272
+ {
273
+ file_provider *provider = calloc(1, sizeof(*provider));
274
+
275
+ if (!provider) {
276
+ return NULL;
277
+ }
278
+
279
+ provider->base.get_cached = get_cached;
280
+ provider->base.refresh = refresh_file;
281
+ provider->base.pause = pause_file;
282
+ provider->base.shutdown = shutdown_file;
283
+ provider->base.dump = do_file_dump;
284
+ provider->base.type = LCB_CLCONFIG_FILE;
285
+ provider->listener.callback = config_listener;
286
+ provider->timer = lcbio_timer_new(parent->iot, provider, async_callback);
287
+
288
+ lcb_confmon_add_listener(parent, &provider->listener);
289
+
290
+ return &provider->base;
291
+ }
292
+
293
+
294
+ static char *mkcachefile(const char *name, const char *bucket)
295
+ {
296
+ if (name != NULL) {
297
+ return strdup(name);
298
+ } else {
299
+ char buffer[1024];
300
+ const char *tmpdir = lcb_get_tmpdir();
301
+
302
+ snprintf(buffer, sizeof(buffer),
303
+ "%s/%s", tmpdir ? tmpdir : ".", bucket);
304
+ return strdup(buffer);
305
+ }
306
+ }
307
+
308
+ int lcb_clconfig_file_set_filename(clconfig_provider *p, const char *f, int ro)
309
+ {
310
+ file_provider *provider = (file_provider *)p;
311
+ lcb_assert(provider->base.type == LCB_CLCONFIG_FILE);
312
+ provider->base.enabled = 1;
313
+
314
+ if (provider->filename) {
315
+ free(provider->filename);
316
+ }
317
+
318
+ provider->filename = mkcachefile(f, p->parent->settings->bucket);
319
+
320
+ if (ro) {
321
+ FILE *fp_tmp;
322
+ provider->ro_mode = 1;
323
+
324
+ fp_tmp = fopen(provider->filename, "r");
325
+ if (!fp_tmp) {
326
+ lcb_log(LOGARGS(provider, ERROR), LOGFMT "Couldn't open for reading: %s", LOGID(provider), strerror(errno));
327
+ return -1;
328
+ } else {
329
+ fclose(fp_tmp);
330
+ }
331
+ }
332
+
333
+ return 0;
334
+ }
335
+
336
+ const char *
337
+ lcb_clconfig_file_get_filename(clconfig_provider *p)
338
+ {
339
+ file_provider *fp = (file_provider *)p;
340
+ return fp->filename;
341
+ }
342
+
343
+ void
344
+ lcb_clconfig_file_set_readonly(clconfig_provider *p, int val)
345
+ {
346
+ ((file_provider *)p)->ro_mode = val;
347
+ }