libcouchbase 1.3.0 → 1.3.2

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 (155) hide show
  1. checksums.yaml +5 -5
  2. data/.travis.yml +2 -2
  3. data/ext/libcouchbase/CMakeLists.txt +51 -25
  4. data/ext/libcouchbase/CONTRIBUTING.md +46 -65
  5. data/ext/libcouchbase/RELEASE_NOTES.markdown +163 -0
  6. data/ext/libcouchbase/cmake/Modules/DownloadLcbDep.cmake +9 -11
  7. data/ext/libcouchbase/cmake/Modules/FindProfiler.cmake +16 -0
  8. data/ext/libcouchbase/cmake/Modules/GetVersionInfo.cmake +6 -6
  9. data/ext/libcouchbase/cmake/config-cmake.h.in +2 -0
  10. data/ext/libcouchbase/cmake/configure +16 -0
  11. data/ext/libcouchbase/example/CMakeLists.txt +17 -2
  12. data/ext/libcouchbase/example/analytics/.gitignore +1 -0
  13. data/ext/libcouchbase/example/analytics/analytics.c +158 -0
  14. data/ext/libcouchbase/example/analytics/build-queries.rb +34 -0
  15. data/ext/libcouchbase/example/analytics/cJSON.c +1 -0
  16. data/ext/libcouchbase/example/analytics/cJSON.h +1 -0
  17. data/ext/libcouchbase/example/analytics/queries.h +113 -0
  18. data/ext/libcouchbase/example/analytics/queries/00-show-dataverse.json +5 -0
  19. data/ext/libcouchbase/example/analytics/queries/01-setup-dataset-breweries.json +6 -0
  20. data/ext/libcouchbase/example/analytics/queries/02-setup-dataset-beers.json +6 -0
  21. data/ext/libcouchbase/example/analytics/queries/03-initiate-shadow.json +6 -0
  22. data/ext/libcouchbase/example/analytics/queries/04-list-datasets.json +7 -0
  23. data/ext/libcouchbase/example/analytics/queries/05-count-breweries.json +5 -0
  24. data/ext/libcouchbase/example/analytics/queries/06-first-brewery.json +6 -0
  25. data/ext/libcouchbase/example/analytics/queries/07-key-based-lookup.json +6 -0
  26. data/ext/libcouchbase/example/analytics/queries/08-exact-match-lookup.json +7 -0
  27. data/ext/libcouchbase/example/analytics/queries/09-exact-match-lookup-different-shape.json +6 -0
  28. data/ext/libcouchbase/example/analytics/queries/10-other-query-filters.json +6 -0
  29. data/ext/libcouchbase/example/analytics/queries/11-equijoin.json +9 -0
  30. data/ext/libcouchbase/example/analytics/queries/12-equijoin-select-star.json +10 -0
  31. data/ext/libcouchbase/example/analytics/queries/13-ansi-join.json +8 -0
  32. data/ext/libcouchbase/example/analytics/queries/14-join-select-values.json +8 -0
  33. data/ext/libcouchbase/example/analytics/queries/15-nested-outer-join.json +7 -0
  34. data/ext/libcouchbase/example/analytics/queries/16-theta-join.json +8 -0
  35. data/ext/libcouchbase/example/analytics/queries/17-existential-quantification.json +9 -0
  36. data/ext/libcouchbase/example/analytics/queries/18-universal-quantification.json +7 -0
  37. data/ext/libcouchbase/example/analytics/queries/19-simple-aggregation.json +6 -0
  38. data/ext/libcouchbase/example/analytics/queries/20-simple-aggregation-unwrapped-value.json +6 -0
  39. data/ext/libcouchbase/example/analytics/queries/21-simple-aggregation-explicit.json +6 -0
  40. data/ext/libcouchbase/example/analytics/queries/22-grouping-and-aggregation.json +6 -0
  41. data/ext/libcouchbase/example/analytics/queries/23-grouping-and-aggregation-with-hint.json +7 -0
  42. data/ext/libcouchbase/example/analytics/queries/24-grouping-and-limits.json +7 -0
  43. data/ext/libcouchbase/example/analytics/queries/25-named-parameters.json +7 -0
  44. data/ext/libcouchbase/example/analytics/queries/26-positional-parameters.json +7 -0
  45. data/ext/libcouchbase/example/crypto/common_provider.c +2 -0
  46. data/ext/libcouchbase/example/crypto/common_provider.h +2 -0
  47. data/ext/libcouchbase/example/crypto/openssl_symmetric_decrypt.c +5 -0
  48. data/ext/libcouchbase/example/crypto/openssl_symmetric_encrypt.c +0 -1
  49. data/ext/libcouchbase/example/crypto/openssl_symmetric_provider.c +16 -26
  50. data/ext/libcouchbase/example/db/db.c +10 -6
  51. data/ext/libcouchbase/example/fts/.gitignore +1 -0
  52. data/ext/libcouchbase/example/fts/build-queries.rb +33 -0
  53. data/ext/libcouchbase/example/fts/fts.c +142 -0
  54. data/ext/libcouchbase/example/fts/queries.h +61 -0
  55. data/ext/libcouchbase/example/fts/queries/00-simple-text-query.json +12 -0
  56. data/ext/libcouchbase/example/fts/queries/01-simple-text-query-on-non-default-index.json +9 -0
  57. data/ext/libcouchbase/example/fts/queries/02-simple-text-query-on-stored-field.json +13 -0
  58. data/ext/libcouchbase/example/fts/queries/03-match-query-with-facet.json +19 -0
  59. data/ext/libcouchbase/example/fts/queries/04-docid-query.json +11 -0
  60. data/ext/libcouchbase/example/fts/queries/05-unanalyzed-term-query-with-fuzziness-level-of-0.json +13 -0
  61. data/ext/libcouchbase/example/fts/queries/06-unanalyzed-term-query-with-fuzziness-level-of-2.json +14 -0
  62. data/ext/libcouchbase/example/fts/queries/07-match-phrase-query.json +13 -0
  63. data/ext/libcouchbase/example/fts/queries/08-phrase-query.json +16 -0
  64. data/ext/libcouchbase/example/fts/queries/09-query-string-query.json +9 -0
  65. data/ext/libcouchbase/example/fts/queries/10-conjunction-query.json +21 -0
  66. data/ext/libcouchbase/example/fts/queries/11-wild-card-query.json +13 -0
  67. data/ext/libcouchbase/example/fts/queries/12-numeric-range-query.json +11 -0
  68. data/ext/libcouchbase/example/fts/queries/13-regexp-query.json +13 -0
  69. data/ext/libcouchbase/example/minimal/.gitignore +1 -0
  70. data/ext/libcouchbase/example/minimal/query.c +185 -0
  71. data/ext/libcouchbase/example/subdoc/subdoc-xattrs.c +2 -2
  72. data/ext/libcouchbase/example/tracing/cJSON.c +1 -1
  73. data/ext/libcouchbase/example/tracing/cJSON.h +1 -1
  74. data/ext/libcouchbase/include/libcouchbase/cbft.h +38 -4
  75. data/ext/libcouchbase/include/libcouchbase/cntl-private.h +8 -97
  76. data/ext/libcouchbase/include/libcouchbase/cntl.h +288 -8
  77. data/ext/libcouchbase/include/libcouchbase/couchbase.h +47 -10
  78. data/ext/libcouchbase/include/libcouchbase/crypto.h +214 -48
  79. data/ext/libcouchbase/include/libcouchbase/deprecated.h +12 -0
  80. data/ext/libcouchbase/include/libcouchbase/error.h +33 -2
  81. data/ext/libcouchbase/include/libcouchbase/ixmgmt.h +1 -1
  82. data/ext/libcouchbase/include/libcouchbase/n1ql.h +87 -13
  83. data/ext/libcouchbase/include/libcouchbase/subdoc.h +3 -7
  84. data/ext/libcouchbase/include/libcouchbase/tracing.h +174 -56
  85. data/ext/libcouchbase/include/libcouchbase/vbucket.h +21 -1
  86. data/ext/libcouchbase/include/libcouchbase/views.h +49 -4
  87. data/ext/libcouchbase/packaging/deb/control +2 -3
  88. data/ext/libcouchbase/packaging/parse-git-describe.pl +1 -1
  89. data/ext/libcouchbase/plugins/io/libev/CMakeLists.txt +7 -5
  90. data/ext/libcouchbase/plugins/io/libevent/CMakeLists.txt +7 -5
  91. data/ext/libcouchbase/plugins/io/libuv/CMakeLists.txt +14 -12
  92. data/ext/libcouchbase/plugins/io/libuv/libuv_compat.h +3 -0
  93. data/ext/libcouchbase/plugins/io/libuv/plugin-libuv.c +14 -6
  94. data/ext/libcouchbase/plugins/io/select/CMakeLists.txt +7 -5
  95. data/ext/libcouchbase/src/bootstrap.cc +6 -1
  96. data/ext/libcouchbase/src/bucketconfig/bc_cccp.cc +2 -7
  97. data/ext/libcouchbase/src/bucketconfig/bc_file.cc +1 -1
  98. data/ext/libcouchbase/src/bucketconfig/bc_http.cc +4 -11
  99. data/ext/libcouchbase/src/bucketconfig/clconfig.h +29 -36
  100. data/ext/libcouchbase/src/bucketconfig/confmon.cc +4 -2
  101. data/ext/libcouchbase/src/cntl.cc +181 -151
  102. data/ext/libcouchbase/src/config_static.h +1 -1
  103. data/ext/libcouchbase/src/connspec.cc +5 -1
  104. data/ext/libcouchbase/src/connspec.h +3 -1
  105. data/ext/libcouchbase/src/crypto.cc +93 -80
  106. data/ext/libcouchbase/src/dns-srv.cc +1 -1
  107. data/ext/libcouchbase/src/handler.cc +0 -1
  108. data/ext/libcouchbase/src/http/http-priv.h +1 -0
  109. data/ext/libcouchbase/src/http/http.cc +1 -2
  110. data/ext/libcouchbase/src/instance.cc +21 -2
  111. data/ext/libcouchbase/src/internal.h +1 -0
  112. data/ext/libcouchbase/src/lcbio/ctx.c +24 -3
  113. data/ext/libcouchbase/src/lcbio/ioutils.cc +1 -1
  114. data/ext/libcouchbase/src/lcbio/rw-inl.h +22 -1
  115. data/ext/libcouchbase/src/lcbio/ssl.h +2 -0
  116. data/ext/libcouchbase/src/mc/compress.cc +18 -11
  117. data/ext/libcouchbase/src/mc/mcreq.c +2 -0
  118. data/ext/libcouchbase/src/mc/mcreq.h +1 -1
  119. data/ext/libcouchbase/src/mcserver/mcserver.cc +163 -6
  120. data/ext/libcouchbase/src/mcserver/negotiate.cc +17 -7
  121. data/ext/libcouchbase/src/n1ql/n1ql.cc +12 -3
  122. data/ext/libcouchbase/src/newconfig.cc +4 -3
  123. data/ext/libcouchbase/src/nodeinfo.cc +1 -7
  124. data/ext/libcouchbase/src/operations/observe.cc +1 -0
  125. data/ext/libcouchbase/src/operations/ping.cc +5 -3
  126. data/ext/libcouchbase/src/retryq.cc +22 -0
  127. data/ext/libcouchbase/src/retryq.h +2 -1
  128. data/ext/libcouchbase/src/rnd.cc +5 -12
  129. data/ext/libcouchbase/src/settings.c +4 -7
  130. data/ext/libcouchbase/src/settings.h +6 -2
  131. data/ext/libcouchbase/src/strcodecs/base64.c +59 -0
  132. data/ext/libcouchbase/src/strcodecs/strcodecs.h +2 -0
  133. data/ext/libcouchbase/src/trace.h +2 -2
  134. data/ext/libcouchbase/src/tracing/span.cc +177 -45
  135. data/ext/libcouchbase/src/tracing/threshold_logging_tracer.cc +70 -28
  136. data/ext/libcouchbase/src/tracing/tracing-internal.h +33 -48
  137. data/ext/libcouchbase/src/vbucket/vbucket.c +146 -30
  138. data/ext/libcouchbase/src/wait.cc +1 -1
  139. data/ext/libcouchbase/tests/CMakeLists.txt +13 -4
  140. data/ext/libcouchbase/tests/iotests/mock-environment.cc +1 -1
  141. data/ext/libcouchbase/tests/iotests/t_misc.cc +2 -2
  142. data/ext/libcouchbase/tests/iotests/t_views.cc +1 -1
  143. data/ext/libcouchbase/tests/iotests/testutil.cc +3 -2
  144. data/ext/libcouchbase/tests/vbucket/confdata/map_node_present_nodesext_missing_nodes.json +94 -0
  145. data/ext/libcouchbase/tests/vbucket/t_config.cc +15 -0
  146. data/ext/libcouchbase/tools/CMakeLists.txt +11 -6
  147. data/ext/libcouchbase/tools/cbc-handlers.h +9 -0
  148. data/ext/libcouchbase/tools/cbc-proxy.cc +1 -1
  149. data/ext/libcouchbase/tools/cbc.cc +33 -5
  150. data/ext/libcouchbase/tools/common/options.cc +1 -1
  151. data/ext/libcouchbase/tools/extract-packets.rb +110 -0
  152. data/lib/libcouchbase/connection.rb +13 -5
  153. data/lib/libcouchbase/ext/tasks.rb +1 -1
  154. data/lib/libcouchbase/version.rb +1 -1
  155. metadata +62 -7
@@ -40,6 +40,8 @@ static void tlt_destructor(lcbtrace_TRACER *wrapper)
40
40
  }
41
41
  if (wrapper->cookie) {
42
42
  ThresholdLoggingTracer *tracer = reinterpret_cast< ThresholdLoggingTracer * >(wrapper->cookie);
43
+ tracer->do_flush_orphans();
44
+ tracer->do_flush_threshold();
43
45
  delete tracer;
44
46
  wrapper->cookie = NULL;
45
47
  }
@@ -53,11 +55,15 @@ static void tlt_report(lcbtrace_TRACER *wrapper, lcbtrace_SPAN *span)
53
55
  }
54
56
 
55
57
  ThresholdLoggingTracer *tracer = reinterpret_cast< ThresholdLoggingTracer * >(wrapper->cookie);
56
- if (span->tags[LCBTRACE_TAG_SERVICE] == LCBTRACE_TAG_SERVICE_KV) {
57
- if (lcbtrace_span_is_orphaned(span)) {
58
- tracer->add_orphan(span);
59
- } else {
60
- tracer->check_threshold(span);
58
+ char *value = NULL;
59
+ size_t nvalue;
60
+ if (lcbtrace_span_get_tag_str(span, LCBTRACE_TAG_SERVICE, &value, &nvalue) == LCB_SUCCESS) {
61
+ if (strncmp(value, LCBTRACE_TAG_SERVICE_KV, nvalue) == 0) {
62
+ if (lcbtrace_span_is_orphaned(span)) {
63
+ tracer->add_orphan(span);
64
+ } else {
65
+ tracer->check_threshold(span);
66
+ }
61
67
  }
62
68
  }
63
69
  }
@@ -77,17 +83,39 @@ lcbtrace_TRACER *ThresholdLoggingTracer::wrap()
77
83
  return m_wrapper;
78
84
  }
79
85
 
80
- ReportedSpan ThresholdLoggingTracer::convert(lcbtrace_SPAN *span)
86
+ QueueEntry ThresholdLoggingTracer::convert(lcbtrace_SPAN *span)
81
87
  {
82
- ReportedSpan orphan;
88
+ QueueEntry orphan;
83
89
  orphan.duration = span->duration();
84
90
  Json::Value entry;
85
- entry["operation_name"] = span->m_opname;
86
- entry["operation_id"] = span->tags[LCBTRACE_TAG_OPERATION_ID];
87
- entry["last_local_id"] = span->tags[LCBTRACE_TAG_LOCAL_ID];
88
- entry["last_local_address"] = span->tags[LCBTRACE_TAG_LOCAL_ADDRESS];
89
- entry["last_remote_address"] = span->tags[LCBTRACE_TAG_PEER_ADDRESS];
90
- entry["server_us"] = span->tags[LCBTRACE_TAG_PEER_LATENCY];
91
+ char *value;
92
+ size_t nvalue;
93
+
94
+ if (lcbtrace_span_get_tag_str(
95
+ span, LCBTRACE_TAG_OPERATION_ID, &value, &nvalue) ==
96
+ LCB_SUCCESS) {
97
+ entry["last_operation_id"] = std::string(span->m_opname) + ":" +
98
+ std::string(value, value + nvalue);
99
+ }
100
+ if (lcbtrace_span_get_tag_str(
101
+ span, LCBTRACE_TAG_LOCAL_ID, &value, &nvalue) == LCB_SUCCESS) {
102
+ entry["last_local_id"] = std::string(value, value + nvalue);
103
+ }
104
+ if (lcbtrace_span_get_tag_str(
105
+ span, LCBTRACE_TAG_LOCAL_ADDRESS, &value, &nvalue) ==
106
+ LCB_SUCCESS) {
107
+ entry["last_local_address"] = std::string(value, value + nvalue);
108
+ }
109
+ if (lcbtrace_span_get_tag_str(
110
+ span, LCBTRACE_TAG_PEER_ADDRESS, &value, &nvalue) ==
111
+ LCB_SUCCESS) {
112
+ entry["last_remote_address"] = std::string(value, value + nvalue);
113
+ }
114
+ uint64_t num;
115
+ if (lcbtrace_span_get_tag_uint64(span, LCBTRACE_TAG_PEER_LATENCY, &num) ==
116
+ LCB_SUCCESS) {
117
+ entry["server_us"] = (Json::UInt64)num;
118
+ }
91
119
  entry["total_us"] = (Json::UInt64)orphan.duration;
92
120
  orphan.payload = Json::FastWriter().write(entry);
93
121
  return orphan;
@@ -105,26 +133,46 @@ void ThresholdLoggingTracer::check_threshold(lcbtrace_SPAN *span)
105
133
  }
106
134
  }
107
135
 
108
- void ThresholdLoggingTracer::flush_queue(FixedQueue< ReportedSpan > &queue, const char *message)
136
+ void ThresholdLoggingTracer::flush_queue(FixedSpanQueue &queue, const char *message, bool warn = false)
109
137
  {
110
- std::vector< ReportedSpan > &slice = queue.get_sorted();
111
138
  Json::Value entries;
112
139
  entries["service"] = "kv";
113
- entries["count"] = (Json::UInt)slice.size();
140
+ entries["count"] = (Json::UInt)queue.size();
114
141
  Json::Value top;
115
- for (size_t ii = 0; ii < slice.size(); ii++) {
142
+ while (!queue.empty())
143
+ {
116
144
  Json::Value entry;
117
- if (Json::Reader().parse(slice[ii].payload, entry)) {
145
+ if (Json::Reader().parse(queue.top().payload, entry)) {
118
146
  top.append(entry);
119
147
  }
148
+ queue.pop();
120
149
  }
121
150
  entries["top"] = top;
122
151
  std::string doc = Json::FastWriter().write(entries);
123
152
  if (doc.size() > 0 && doc[doc.size() - 1] == '\n') {
124
153
  doc[doc.size() - 1] = '\0';
125
154
  }
126
- lcb_log(LOGARGS(this, WARN), "%s: %s", message, doc.c_str());
127
- queue.clear();
155
+ if (warn) {
156
+ lcb_log(LOGARGS(this, WARN), "%s: %s", message, doc.c_str());
157
+ } else {
158
+ lcb_log(LOGARGS(this, INFO), "%s: %s", message, doc.c_str());
159
+ }
160
+ }
161
+
162
+ void ThresholdLoggingTracer::do_flush_orphans()
163
+ {
164
+ if (m_orphans.empty()) {
165
+ return;
166
+ }
167
+ flush_queue(m_orphans, "Orphan responses observed", true);
168
+ }
169
+
170
+ void ThresholdLoggingTracer::do_flush_threshold()
171
+ {
172
+ if (m_threshold.empty()) {
173
+ return;
174
+ }
175
+ flush_queue(m_threshold, "Operations over threshold");
128
176
  }
129
177
 
130
178
  void ThresholdLoggingTracer::flush_orphans()
@@ -135,10 +183,7 @@ void ThresholdLoggingTracer::flush_orphans()
135
183
  } else {
136
184
  m_oflush.rearm(tv);
137
185
  }
138
- if (m_orphans.empty()) {
139
- return;
140
- }
141
- flush_queue(m_orphans, "Orphan responses observed");
186
+ do_flush_orphans();
142
187
  }
143
188
 
144
189
  void ThresholdLoggingTracer::flush_threshold()
@@ -149,10 +194,7 @@ void ThresholdLoggingTracer::flush_threshold()
149
194
  } else {
150
195
  m_tflush.rearm(tv);
151
196
  }
152
- if (m_threshold.empty()) {
153
- return;
154
- }
155
- flush_queue(m_threshold, "Operations over threshold");
197
+ do_flush_threshold();
156
198
  }
157
199
 
158
200
  ThresholdLoggingTracer::ThresholdLoggingTracer(lcb_t instance)
@@ -35,6 +35,7 @@ class Span
35
35
  {
36
36
  public:
37
37
  Span(lcbtrace_TRACER *tracer, const char *opname, uint64_t start, lcbtrace_REF_TYPE ref, lcbtrace_SPAN *other);
38
+ ~Span();
38
39
 
39
40
  void finish(uint64_t finish);
40
41
  uint64_t duration()
@@ -42,7 +43,11 @@ class Span
42
43
  return m_finish - m_start;
43
44
  }
44
45
 
45
- template < typename T > void add_tag(const char *name, T value);
46
+ void add_tag(const char *name, int copy, const char *value);
47
+ void add_tag(const char *name, int copy, const char *value, size_t value_len);
48
+ void add_tag(const char *name, int copy, uint64_t value);
49
+ void add_tag(const char *name, int copy, double value);
50
+ void add_tag(const char *name, int copy, bool value);
46
51
 
47
52
  lcbtrace_TRACER *m_tracer;
48
53
  std::string m_opname;
@@ -50,8 +55,8 @@ class Span
50
55
  uint64_t m_start;
51
56
  uint64_t m_finish;
52
57
  bool m_orphaned;
53
- Json::Value tags;
54
58
  Span *m_parent;
59
+ sllist_root m_tags;
55
60
  };
56
61
 
57
62
  struct ReportedSpan {
@@ -64,61 +69,37 @@ struct ReportedSpan {
64
69
  }
65
70
  };
66
71
 
67
- template < typename T > class FixedQueue
72
+ template < typename T > class FixedQueue: private std::priority_queue<T>
68
73
  {
69
74
  public:
70
75
  explicit FixedQueue(size_t capacity) : m_capacity(capacity) {}
71
76
 
72
- void push(T item)
73
- {
74
- if (m_items.size() < m_capacity) {
75
- m_items.push_back(item);
76
- std::push_heap(m_items.begin(), m_items.end());
77
- } else {
78
- std::sort_heap(m_items.begin(), m_items.end());
79
- if (m_items.front() < item) {
80
- m_items[0] = item;
81
- }
82
- std::make_heap(m_items.begin(), m_items.end());
77
+ void push(const T& item) {
78
+ std::priority_queue<T>::push(item);
79
+ if (this->size() > m_capacity) {
80
+ this->c.pop_back();
83
81
  }
84
82
  }
85
-
86
- size_t size()
87
- {
88
- return m_items.size();
89
- }
90
-
91
- bool empty()
92
- {
93
- return m_items.empty();
94
- }
95
-
96
- void clear()
97
- {
98
- m_items.clear();
99
- }
100
-
101
- std::vector< T > &get_sorted()
102
- {
103
- std::sort_heap(m_items.begin(), m_items.end());
104
- return m_items;
105
- }
106
-
83
+ using std::priority_queue<T>::empty;
84
+ using std::priority_queue<T>::top;
85
+ using std::priority_queue<T>::pop;
86
+ using std::priority_queue<T>::size;
107
87
  private:
108
88
  size_t m_capacity;
109
- std::vector< T > m_items;
110
89
  };
111
90
 
91
+ typedef ReportedSpan QueueEntry;
92
+ typedef FixedQueue<QueueEntry> FixedSpanQueue;
112
93
  class ThresholdLoggingTracer
113
94
  {
114
95
  lcbtrace_TRACER *m_wrapper;
115
96
  lcb_settings *m_settings;
116
97
 
117
- FixedQueue< ReportedSpan > m_orphans;
118
- FixedQueue< ReportedSpan > m_threshold;
98
+ FixedSpanQueue m_orphans;
99
+ FixedSpanQueue m_threshold;
119
100
 
120
- void flush_queue(FixedQueue< ReportedSpan > &queue, const char *message);
121
- ReportedSpan convert(lcbtrace_SPAN *span);
101
+ void flush_queue(FixedSpanQueue &queue, const char *message, bool warn);
102
+ QueueEntry convert(lcbtrace_SPAN *span);
122
103
 
123
104
  public:
124
105
  ThresholdLoggingTracer(lcb_t instance);
@@ -129,6 +110,8 @@ class ThresholdLoggingTracer
129
110
 
130
111
  void flush_orphans();
131
112
  void flush_threshold();
113
+ void do_flush_orphans();
114
+ void do_flush_threshold();
132
115
 
133
116
  lcb::io::Timer< ThresholdLoggingTracer, &ThresholdLoggingTracer::flush_orphans > m_oflush;
134
117
  lcb::io::Timer< ThresholdLoggingTracer, &ThresholdLoggingTracer::flush_threshold > m_tflush;
@@ -164,14 +147,16 @@ void lcbtrace_span_set_orphaned(lcbtrace_SPAN *span, int val);
164
147
  if (span) { \
165
148
  lcbtrace_span_add_tag_uint64(span, LCBTRACE_TAG_PEER_LATENCY, (response)->duration()); \
166
149
  lcb::Server *server = static_cast< lcb::Server * >(pipeline); \
167
- const lcb_host_t &remote = server->get_host(); \
168
- std::string hh; \
169
- if (remote.ipv6) { \
170
- hh.append("[").append(remote.host).append("]:").append(remote.port); \
171
- } else { \
172
- hh.append(remote.host).append(":").append(remote.port); \
150
+ const lcb_host_t *remote = server->curhost; \
151
+ if (remote) { \
152
+ std::string hh; \
153
+ if (remote->ipv6) { \
154
+ hh.append("[").append(remote->host).append("]:").append(remote->port); \
155
+ } else { \
156
+ hh.append(remote->host).append(":").append(remote->port); \
157
+ } \
158
+ lcbtrace_span_add_tag_str(span, LCBTRACE_TAG_PEER_ADDRESS, hh.c_str()); \
173
159
  } \
174
- lcbtrace_span_add_tag_str(span, LCBTRACE_TAG_PEER_ADDRESS, hh.c_str()); \
175
160
  lcbio_CTX *ctx = server->connctx; \
176
161
  if (ctx) { \
177
162
  char local_id[34] = {}; \
@@ -385,7 +385,7 @@ build_server_strings(lcbvb_CONFIG *cfg, lcbvb_SERVER *server)
385
385
  * @return
386
386
  */
387
387
  static int
388
- build_server_3x(lcbvb_CONFIG *cfg, lcbvb_SERVER *server, cJSON *js)
388
+ build_server_3x(lcbvb_CONFIG *cfg, lcbvb_SERVER *server, cJSON *js, char **network)
389
389
  {
390
390
  cJSON *jsvcs;
391
391
  char *htmp;
@@ -414,6 +414,37 @@ build_server_3x(lcbvb_CONFIG *cfg, lcbvb_SERVER *server, cJSON *js)
414
414
  goto GT_ERR;
415
415
  }
416
416
 
417
+ if (network && *network && strcmp(*network, "default") != 0) {
418
+ cJSON *jaltaddr = cJSON_GetObjectItem(js, "alternateAddresses");
419
+ if (jaltaddr && jaltaddr->type == cJSON_Object) {
420
+ cJSON *jnetwork = cJSON_GetObjectItem(jaltaddr, *network);
421
+ if (jnetwork && get_jstr(jnetwork, "hostname", &htmp)) {
422
+ cJSON *jports;
423
+ server->alt_hostname = strdup(htmp);
424
+ jports = cJSON_GetObjectItem(jnetwork, "ports");
425
+ if (jports && jports->type == cJSON_Object) {
426
+ extract_services(cfg, jports, &server->alt_svc, 0);
427
+ extract_services(cfg, jports, &server->alt_svc_ssl, 1);
428
+ }
429
+
430
+ #define COPY_SERVICE(src, dst) \
431
+ if ((dst)->data == 0) (dst)->data = (src)->data; \
432
+ if ((dst)->mgmt == 0) (dst)->mgmt = (src)->mgmt; \
433
+ if ((dst)->views == 0) (dst)->views = (src)->views; \
434
+ if ((dst)->n1ql == 0) (dst)->n1ql = (src)->n1ql; \
435
+ if ((dst)->fts == 0) (dst)->fts = (src)->fts; \
436
+ if ((dst)->ixadmin == 0) (dst)->ixadmin = (src)->ixadmin; \
437
+ if ((dst)->ixquery == 0) (dst)->ixquery = (src)->ixquery; \
438
+ if ((dst)->cbas == 0) (dst)->cbas = (src)->cbas;
439
+
440
+ COPY_SERVICE(&server->svc, &server->alt_svc);
441
+ COPY_SERVICE(&server->svc_ssl, &server->alt_svc_ssl);
442
+
443
+ #undef COPY_SERVICE
444
+ }
445
+ }
446
+ }
447
+
417
448
  return 1;
418
449
 
419
450
  GT_ERR:
@@ -427,7 +458,7 @@ build_server_3x(lcbvb_CONFIG *cfg, lcbvb_SERVER *server, cJSON *js)
427
458
  * @return nonzero on success, 0 on failure.
428
459
  */
429
460
  static int
430
- build_server_2x(lcbvb_CONFIG *cfg, lcbvb_SERVER *server, cJSON *js)
461
+ build_server_2x(lcbvb_CONFIG *cfg, lcbvb_SERVER *server, cJSON *js, char **network)
431
462
  {
432
463
  char *tmp = NULL, *colon;
433
464
  int itmp;
@@ -508,12 +539,49 @@ build_server_2x(lcbvb_CONFIG *cfg, lcbvb_SERVER *server, cJSON *js)
508
539
  return 0;
509
540
  }
510
541
 
542
+ static void
543
+ guess_network(cJSON *jnodes, int nsrv, const char *source, char **network)
544
+ {
545
+ int ii;
546
+ for (ii = 0; ii < nsrv; ii++) {
547
+ cJSON *jsrv = cJSON_GetArrayItem(jnodes, ii);
548
+ {
549
+ cJSON *jhostname = cJSON_GetObjectItem(jsrv, "hostname");
550
+ if (jhostname && jhostname->type == cJSON_String) {
551
+ if (strcmp(jhostname->valuestring, source) == 0) {
552
+ *network = strdup("default");
553
+ return;
554
+ }
555
+ }
556
+ }
557
+ {
558
+ cJSON *jaltaddr = cJSON_GetObjectItem(jsrv, "alternateAddresses");
559
+ if (jaltaddr && jaltaddr->type == cJSON_Object) {
560
+ cJSON *cur;
561
+ for (cur = jaltaddr->child; cur != NULL; cur = cur->next) {
562
+ if (cur->type == cJSON_Object) {
563
+ cJSON *jhostname = cJSON_GetObjectItem(cur, "hostname");
564
+ if (jhostname && jhostname->type == cJSON_String) {
565
+ if (strcmp(jhostname->valuestring, source) == 0) {
566
+ *network = strdup(cur->string);
567
+ return;
568
+ }
569
+ }
570
+ }
571
+ }
572
+ }
573
+ }
574
+ }
575
+ *network = strdup("default");
576
+ }
577
+
511
578
  int
512
- lcbvb_load_json(lcbvb_CONFIG *cfg, const char *data)
579
+ lcbvb_load_json_ex(lcbvb_CONFIG *cfg, const char *data, const char *source, char **network)
513
580
  {
514
- cJSON *cj = NULL, *jnodes = NULL;
581
+ cJSON *cj = NULL, *jnodes_ext = NULL, *jnodes = NULL;
515
582
  char *tmp = NULL;
516
- unsigned ii;
583
+ unsigned ii, jnodes_size = 0;
584
+ int jnodes_defined = 0;
517
585
 
518
586
  if ((cj = cJSON_Parse(data)) == NULL) {
519
587
  SET_ERRSTR(cfg, "Couldn't parse JSON");
@@ -531,9 +599,16 @@ lcbvb_load_json(lcbvb_CONFIG *cfg, const char *data)
531
599
  goto GT_ERROR;
532
600
  }
533
601
 
534
- if (get_jarray(cj, "nodesExt", &jnodes)) {
602
+ get_jarray(cj, "nodes", &jnodes);
603
+ if (jnodes) {
604
+ jnodes_defined = 1;
605
+ jnodes_size = cJSON_GetArraySize(jnodes);
606
+ }
607
+ if (get_jarray(cj, "nodesExt", &jnodes_ext)) {
535
608
  cfg->is3x = 1;
536
- } else if (!get_jarray(cj, "nodes", &jnodes)) {
609
+ cfg->nsrv = cJSON_GetArraySize(jnodes_ext);
610
+ jnodes = jnodes_ext;
611
+ } else if (jnodes == NULL) {
537
612
  SET_ERRSTR(cfg, "expected 'nodesExt' or 'nodes' array");
538
613
  goto GT_ERROR;
539
614
  }
@@ -585,6 +660,10 @@ lcbvb_load_json(lcbvb_CONFIG *cfg, const char *data)
585
660
  /** Get the number of nodes. This traverses the list. Yuck */
586
661
  cfg->nsrv = cJSON_GetArraySize(jnodes);
587
662
 
663
+ if (network && *network == NULL) {
664
+ guess_network(jnodes, cfg->nsrv, source, network);
665
+ }
666
+
588
667
  /** Allocate a temporary one on the heap */
589
668
  cfg->servers = calloc(cfg->nsrv, sizeof(*cfg->servers));
590
669
  for (ii = 0; ii < cfg->nsrv; ii++) {
@@ -592,9 +671,15 @@ lcbvb_load_json(lcbvb_CONFIG *cfg, const char *data)
592
671
  cJSON *jsrv = cJSON_GetArrayItem(jnodes, ii);
593
672
 
594
673
  if (cfg->is3x) {
595
- rv = build_server_3x(cfg, cfg->servers + ii, jsrv);
674
+ rv = build_server_3x(cfg, cfg->servers + ii, jsrv, network);
675
+ if (jnodes_defined && rv && ii >= jnodes_size) {
676
+ cfg->servers[ii].svc.data = 0;
677
+ cfg->servers[ii].svc_ssl.data = 0;
678
+ cfg->servers[ii].alt_svc.data = 0;
679
+ cfg->servers[ii].alt_svc_ssl.data = 0;
680
+ }
596
681
  } else {
597
- rv = build_server_2x(cfg, cfg->servers + ii, jsrv);
682
+ rv = build_server_2x(cfg, cfg->servers + ii, jsrv, network);
598
683
  }
599
684
 
600
685
  if (!rv) {
@@ -638,6 +723,12 @@ lcbvb_load_json(lcbvb_CONFIG *cfg, const char *data)
638
723
  return -1;
639
724
  }
640
725
 
726
+ int
727
+ lcbvb_load_json(lcbvb_CONFIG *cfg, const char *data)
728
+ {
729
+ return lcbvb_load_json_ex(cfg, data, NULL, NULL);
730
+ }
731
+
641
732
  static void
642
733
  replace_hoststr(char **orig, const char *replacement)
643
734
  {
@@ -754,6 +845,9 @@ lcbvb_destroy(lcbvb_CONFIG *conf)
754
845
  free_service_strs(&srv->svc);
755
846
  free_service_strs(&srv->svc_ssl);
756
847
  free(srv->authority);
848
+ free(srv->alt_hostname);
849
+ free_service_strs(&srv->alt_svc);
850
+ free_service_strs(&srv->alt_svc_ssl);
757
851
  }
758
852
  free(conf->servers);
759
853
  free(conf->continuum);
@@ -783,6 +877,9 @@ svcs_to_json(lcbvb_SERVICES *svc, cJSON *jsvc, int is_ssl)
783
877
  EXTRACT_SERVICE("n1ql", n1ql);
784
878
  EXTRACT_SERVICE("indexScan", ixquery);
785
879
  EXTRACT_SERVICE("indexAdmin", ixadmin);
880
+ EXTRACT_SERVICE("fts", fts);
881
+ EXTRACT_SERVICE("cbas", cbas);
882
+
786
883
  #undef EXTRACT_SERVICE
787
884
  }
788
885
 
@@ -1139,12 +1236,41 @@ lcbvb_get_changetype(lcbvb_CONFIGDIFF *diff)
1139
1236
  ** String/Port Getters **
1140
1237
  ******************************************************************************
1141
1238
  ******************************************************************************/
1239
+
1240
+ static const lcbvb_SERVICES *
1241
+ get_svc(const lcbvb_SERVER *srv, lcbvb_SVCMODE mode)
1242
+ {
1243
+ if (srv->alt_hostname) {
1244
+ if (mode == LCBVB_SVCMODE_PLAIN) {
1245
+ return &srv->alt_svc;
1246
+ } else {
1247
+ return &srv->alt_svc_ssl;
1248
+ }
1249
+ } else {
1250
+ if (mode == LCBVB_SVCMODE_PLAIN) {
1251
+ return &srv->svc;
1252
+ } else {
1253
+ return &srv->svc_ssl;
1254
+ }
1255
+ }
1256
+ }
1257
+
1258
+ static const char *
1259
+ get_hostname(const lcbvb_SERVER *srv)
1260
+ {
1261
+ if (srv->alt_hostname) {
1262
+ return srv->alt_hostname;
1263
+ } else {
1264
+ return srv->hostname;
1265
+ }
1266
+ }
1267
+
1142
1268
  LIBCOUCHBASE_API
1143
1269
  unsigned
1144
1270
  lcbvb_get_port(lcbvb_CONFIG *cfg,
1145
1271
  unsigned ix, lcbvb_SVCTYPE type, lcbvb_SVCMODE mode)
1146
1272
  {
1147
- lcbvb_SERVICES *svc;
1273
+ const lcbvb_SERVICES *svc;
1148
1274
  lcbvb_SERVER *srv;
1149
1275
  if (type >= LCBVB_SVCTYPE__MAX || mode >= LCBVB_SVCMODE__MAX) {
1150
1276
  return 0;
@@ -1154,12 +1280,7 @@ lcbvb_get_port(lcbvb_CONFIG *cfg,
1154
1280
  }
1155
1281
 
1156
1282
  srv = cfg->servers + ix;
1157
-
1158
- if (mode == LCBVB_SVCMODE_PLAIN) {
1159
- svc = &srv->svc;
1160
- } else {
1161
- svc = &srv->svc_ssl;
1162
- }
1283
+ svc = get_svc(srv, mode);
1163
1284
 
1164
1285
  if (type == LCBVB_SVCTYPE_DATA) {
1165
1286
  return svc->data;
@@ -1197,17 +1318,13 @@ lcbvb_get_hostport(lcbvb_CONFIG *cfg,
1197
1318
  }
1198
1319
 
1199
1320
  srv = cfg->servers + ix;
1200
- if (mode == LCBVB_SVCMODE_PLAIN) {
1201
- svc = &srv->svc;
1202
- } else {
1203
- svc = &srv->svc_ssl;
1204
- }
1321
+ svc = (lcbvb_SERVICES *)get_svc(srv, mode);
1205
1322
 
1206
1323
  strp = &svc->hoststrs[type];
1207
1324
  if (*strp == NULL) {
1208
1325
  size_t strn = strlen(srv->hostname) + 20;
1209
1326
  *strp = calloc(strn, sizeof(char));
1210
- copy_address(*strp, strn, srv->hostname, port);
1327
+ copy_address(*strp, strn, get_hostname(srv), port);
1211
1328
  }
1212
1329
  return *strp;
1213
1330
  }
@@ -1217,7 +1334,7 @@ const char *
1217
1334
  lcbvb_get_hostname(const lcbvb_CONFIG *cfg, unsigned ix)
1218
1335
  {
1219
1336
  if (cfg->nsrv > ix) {
1220
- return cfg->servers[ix].hostname;
1337
+ return get_hostname(cfg->servers + ix);
1221
1338
  } else {
1222
1339
  return NULL;
1223
1340
  }
@@ -1237,8 +1354,7 @@ lcbvb_get_randhost_ex(const lcbvb_CONFIG *cfg,
1237
1354
  */
1238
1355
  for (nn = 0; nn < cfg->nsrv; nn++) {
1239
1356
  const lcbvb_SERVER *server = cfg->servers + nn;
1240
- const lcbvb_SERVICES *svcs = mode == LCBVB_SVCMODE_PLAIN ?
1241
- &server->svc : &server->svc_ssl;
1357
+ const lcbvb_SERVICES *svcs = get_svc(server, mode);
1242
1358
  int has_svc = 0;
1243
1359
 
1244
1360
  // Check if this node is in the exclude list
@@ -1299,11 +1415,10 @@ lcbvb_get_resturl(lcbvb_CONFIG *cfg, unsigned ix,
1299
1415
  srv = cfg->servers + ix;
1300
1416
  if (mode == LCBVB_SVCMODE_PLAIN) {
1301
1417
  prefix = "http";
1302
- svcs = &srv->svc;
1303
1418
  } else {
1304
1419
  prefix = "https";
1305
- svcs = &srv->svc_ssl;
1306
1420
  }
1421
+ svcs = (lcbvb_SERVICES *)get_svc(srv, mode);
1307
1422
 
1308
1423
  if (svc == LCBVB_SVCTYPE_VIEWS) {
1309
1424
  path = srv->viewpath;
@@ -1326,11 +1441,12 @@ lcbvb_get_resturl(lcbvb_CONFIG *cfg, unsigned ix,
1326
1441
  return NULL;
1327
1442
  } else if (!*strp) {
1328
1443
  char buf[4096];
1329
- if (strchr(srv->hostname, ':')) {
1444
+ const char *hostname = get_hostname(srv);
1445
+ if (strchr(hostname, ':')) {
1330
1446
  // IPv6 and should be bracketed
1331
- snprintf(buf, sizeof(buf), "%s://[%s]:%d%s", prefix, srv->hostname, port, path);
1447
+ snprintf(buf, sizeof(buf), "%s://[%s]:%d%s", prefix, hostname, port, path);
1332
1448
  } else {
1333
- snprintf(buf, sizeof(buf), "%s://%s:%d%s", prefix, srv->hostname, port, path);
1449
+ snprintf(buf, sizeof(buf), "%s://%s:%d%s", prefix, hostname, port, path);
1334
1450
  }
1335
1451
  *strp = strdup(buf);
1336
1452
  }