couchbase 3.4.2 → 3.4.4

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 (355) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +2 -2
  3. data/ext/couchbase/CMakeLists.txt +71 -7
  4. data/ext/couchbase/cmake/Documentation.cmake +0 -1
  5. data/ext/couchbase/cmake/OpenSSL.cmake +98 -3
  6. data/ext/couchbase/cmake/Testing.cmake +12 -4
  7. data/ext/couchbase/cmake/build_config.hxx.in +3 -0
  8. data/ext/couchbase/core/bucket.cxx +183 -151
  9. data/ext/couchbase/core/bucket.hxx +23 -1
  10. data/ext/couchbase/core/cluster.hxx +51 -13
  11. data/ext/couchbase/core/cluster_options.cxx +2 -2
  12. data/ext/couchbase/core/cluster_options.hxx +7 -6
  13. data/ext/couchbase/core/cluster_options_fwd.hxx +26 -0
  14. data/ext/couchbase/core/config_profile.hxx +1 -54
  15. data/ext/couchbase/core/config_profiles.cxx +79 -0
  16. data/ext/couchbase/core/config_profiles.hxx +56 -0
  17. data/ext/couchbase/core/crud_component.cxx +51 -22
  18. data/ext/couchbase/core/error_context/key_value.cxx +2 -1
  19. data/ext/couchbase/core/error_context/key_value.hxx +10 -12
  20. data/ext/couchbase/core/error_context/search.hxx +1 -1
  21. data/ext/couchbase/core/impl/analytics.cxx +1 -0
  22. data/ext/couchbase/core/impl/boolean_field_query.cxx +40 -0
  23. data/ext/couchbase/core/impl/boolean_query.cxx +62 -0
  24. data/ext/couchbase/core/impl/build_deferred_query_indexes.cxx +115 -50
  25. data/ext/couchbase/core/impl/cluster.cxx +8 -0
  26. data/ext/couchbase/core/impl/conjunction_query.cxx +51 -0
  27. data/ext/couchbase/core/impl/create_bucket.cxx +155 -0
  28. data/ext/couchbase/core/impl/create_query_index.cxx +172 -59
  29. data/ext/couchbase/core/impl/date_range.cxx +89 -0
  30. data/ext/couchbase/core/impl/date_range_facet.cxx +54 -0
  31. data/ext/couchbase/core/impl/date_range_facet_result.cxx +64 -0
  32. data/ext/couchbase/core/impl/date_range_query.cxx +125 -0
  33. data/ext/couchbase/core/impl/disjunction_query.cxx +51 -0
  34. data/ext/couchbase/core/impl/dns_srv_tracker.cxx +2 -1
  35. data/ext/couchbase/core/impl/drop_bucket.cxx +66 -0
  36. data/ext/couchbase/core/impl/drop_query_index.cxx +138 -59
  37. data/ext/couchbase/core/impl/encoded_search_facet.hxx +29 -0
  38. data/ext/couchbase/core/impl/encoded_search_query.hxx +29 -0
  39. data/ext/couchbase/core/impl/encoded_search_sort.hxx +29 -0
  40. data/ext/couchbase/core/impl/flush_bucket.cxx +66 -0
  41. data/ext/couchbase/core/impl/geo_bounding_box_query.cxx +46 -0
  42. data/ext/couchbase/core/impl/geo_distance_query.cxx +43 -0
  43. data/ext/couchbase/core/impl/geo_polygon_query.cxx +46 -0
  44. data/ext/couchbase/core/impl/get_all_buckets.cxx +163 -0
  45. data/ext/couchbase/core/impl/get_all_query_indexes.cxx +67 -37
  46. data/ext/couchbase/core/impl/get_bucket.cxx +153 -0
  47. data/ext/couchbase/core/impl/internal_date_range_facet_result.cxx +80 -0
  48. data/ext/couchbase/core/impl/internal_date_range_facet_result.hxx +48 -0
  49. data/ext/couchbase/core/impl/internal_manager_error_context.cxx +113 -0
  50. data/ext/couchbase/core/impl/internal_manager_error_context.hxx +60 -0
  51. data/ext/couchbase/core/impl/internal_numeric_range_facet_result.cxx +80 -0
  52. data/ext/couchbase/core/impl/internal_numeric_range_facet_result.hxx +48 -0
  53. data/ext/couchbase/core/impl/internal_search_error_context.cxx +141 -0
  54. data/ext/couchbase/core/impl/internal_search_error_context.hxx +61 -0
  55. data/ext/couchbase/core/impl/internal_search_meta_data.cxx +60 -0
  56. data/ext/couchbase/core/impl/internal_search_meta_data.hxx +41 -0
  57. data/ext/couchbase/core/impl/internal_search_result.cxx +84 -0
  58. data/ext/couchbase/core/impl/internal_search_result.hxx +43 -0
  59. data/ext/couchbase/core/impl/internal_search_row.cxx +82 -0
  60. data/ext/couchbase/core/impl/internal_search_row.hxx +56 -0
  61. data/ext/couchbase/core/impl/internal_search_row_location.hxx +32 -0
  62. data/ext/couchbase/core/impl/internal_search_row_locations.cxx +137 -0
  63. data/ext/couchbase/core/impl/internal_search_row_locations.hxx +45 -0
  64. data/ext/couchbase/core/impl/internal_term_facet_result.cxx +80 -0
  65. data/ext/couchbase/core/impl/internal_term_facet_result.hxx +48 -0
  66. data/ext/couchbase/core/impl/key_value_error_category.cxx +2 -4
  67. data/ext/couchbase/core/impl/key_value_error_context.cxx +98 -0
  68. data/ext/couchbase/core/impl/lookup_in.cxx +1 -0
  69. data/ext/couchbase/core/impl/lookup_in_all_replicas.cxx +176 -0
  70. data/ext/couchbase/core/impl/lookup_in_all_replicas.hxx +80 -0
  71. data/ext/couchbase/core/impl/lookup_in_any_replica.cxx +167 -0
  72. data/ext/couchbase/core/impl/lookup_in_any_replica.hxx +75 -0
  73. data/ext/couchbase/core/impl/lookup_in_replica.cxx +97 -0
  74. data/ext/couchbase/core/impl/lookup_in_replica.hxx +67 -0
  75. data/ext/couchbase/core/impl/manager_error_context.cxx +100 -0
  76. data/ext/couchbase/core/impl/match_all_query.cxx +35 -0
  77. data/ext/couchbase/core/impl/match_none_query.cxx +35 -0
  78. data/ext/couchbase/core/impl/match_phrase_query.cxx +43 -0
  79. data/ext/couchbase/core/impl/match_query.cxx +59 -0
  80. data/ext/couchbase/core/impl/numeric_range.cxx +49 -0
  81. data/ext/couchbase/core/impl/numeric_range_facet.cxx +54 -0
  82. data/ext/couchbase/core/impl/numeric_range_facet_result.cxx +64 -0
  83. data/ext/couchbase/core/impl/numeric_range_query.cxx +56 -0
  84. data/ext/couchbase/core/impl/phrase_query.cxx +42 -0
  85. data/ext/couchbase/core/impl/prefix_query.cxx +40 -0
  86. data/ext/couchbase/core/impl/query.cxx +1 -0
  87. data/ext/couchbase/core/impl/query_error_context.cxx +75 -0
  88. data/ext/couchbase/core/impl/query_string_query.cxx +37 -0
  89. data/ext/couchbase/core/impl/regexp_query.cxx +40 -0
  90. data/ext/couchbase/core/impl/search.cxx +191 -0
  91. data/ext/couchbase/core/impl/search_error_context.cxx +147 -0
  92. data/ext/couchbase/core/impl/search_meta_data.cxx +46 -0
  93. data/ext/couchbase/core/impl/search_result.cxx +66 -0
  94. data/ext/couchbase/core/impl/search_row.cxx +74 -0
  95. data/ext/couchbase/core/impl/search_row_location.cxx +64 -0
  96. data/ext/couchbase/core/impl/search_row_locations.cxx +66 -0
  97. data/ext/couchbase/core/impl/search_sort_field.cxx +104 -0
  98. data/ext/couchbase/core/impl/search_sort_id.cxx +43 -0
  99. data/ext/couchbase/core/impl/search_sort_score.cxx +43 -0
  100. data/ext/couchbase/core/impl/term_facet.cxx +36 -0
  101. data/ext/couchbase/core/impl/term_facet_result.cxx +64 -0
  102. data/ext/couchbase/core/impl/term_query.cxx +56 -0
  103. data/ext/couchbase/core/impl/term_range_query.cxx +57 -0
  104. data/ext/couchbase/core/impl/update_bucket.cxx +130 -0
  105. data/ext/couchbase/core/impl/watch_query_indexes.cxx +53 -29
  106. data/ext/couchbase/core/impl/wildcard_query.cxx +40 -0
  107. data/ext/couchbase/core/io/dns_client.cxx +111 -40
  108. data/ext/couchbase/core/io/dns_config.cxx +5 -4
  109. data/ext/couchbase/core/io/http_context.hxx +1 -1
  110. data/ext/couchbase/core/io/http_session.hxx +34 -1
  111. data/ext/couchbase/core/io/http_session_manager.hxx +5 -3
  112. data/ext/couchbase/core/io/mcbp_command.hxx +9 -2
  113. data/ext/couchbase/core/io/mcbp_session.cxx +106 -42
  114. data/ext/couchbase/core/io/mcbp_session.hxx +4 -3
  115. data/ext/couchbase/core/io/retry_orchestrator.hxx +3 -2
  116. data/ext/couchbase/core/json_string.hxx +5 -0
  117. data/ext/couchbase/core/logger/custom_rotating_file_sink.cxx +1 -1
  118. data/ext/couchbase/core/logger/logger.cxx +80 -20
  119. data/ext/couchbase/core/logger/logger.hxx +31 -0
  120. data/ext/couchbase/core/meta/features.hxx +25 -0
  121. data/ext/couchbase/core/meta/version.cxx +18 -4
  122. data/ext/couchbase/core/mozilla_ca_bundle.hxx +39 -0
  123. data/ext/couchbase/core/operations/document_analytics.cxx +1 -0
  124. data/ext/couchbase/core/operations/document_analytics.hxx +1 -0
  125. data/ext/couchbase/core/operations/document_append.hxx +1 -1
  126. data/ext/couchbase/core/operations/document_decrement.hxx +1 -1
  127. data/ext/couchbase/core/operations/document_exists.hxx +1 -1
  128. data/ext/couchbase/core/operations/document_get.hxx +1 -1
  129. data/ext/couchbase/core/operations/document_get_and_lock.hxx +1 -1
  130. data/ext/couchbase/core/operations/document_get_and_touch.hxx +1 -1
  131. data/ext/couchbase/core/operations/document_get_projected.hxx +1 -1
  132. data/ext/couchbase/core/operations/document_increment.hxx +1 -1
  133. data/ext/couchbase/core/operations/document_insert.hxx +1 -1
  134. data/ext/couchbase/core/operations/document_lookup_in.hxx +1 -1
  135. data/ext/couchbase/core/operations/document_lookup_in_all_replicas.hxx +192 -0
  136. data/ext/couchbase/core/operations/document_lookup_in_any_replica.hxx +188 -0
  137. data/ext/couchbase/core/operations/document_mutate_in.hxx +1 -1
  138. data/ext/couchbase/core/operations/document_prepend.hxx +1 -1
  139. data/ext/couchbase/core/operations/document_query.cxx +13 -0
  140. data/ext/couchbase/core/operations/document_query.hxx +7 -0
  141. data/ext/couchbase/core/operations/document_remove.hxx +1 -1
  142. data/ext/couchbase/core/operations/document_replace.hxx +1 -1
  143. data/ext/couchbase/core/operations/document_search.cxx +4 -1
  144. data/ext/couchbase/core/operations/document_search.hxx +2 -1
  145. data/ext/couchbase/core/operations/document_touch.hxx +1 -1
  146. data/ext/couchbase/core/operations/document_unlock.hxx +1 -1
  147. data/ext/couchbase/core/operations/document_upsert.hxx +1 -1
  148. data/ext/couchbase/core/operations/document_view.hxx +1 -0
  149. data/ext/couchbase/core/operations.hxx +2 -0
  150. data/ext/couchbase/core/origin.cxx +270 -0
  151. data/ext/couchbase/core/origin.hxx +2 -0
  152. data/ext/couchbase/core/protocol/client_request.hxx +11 -2
  153. data/ext/couchbase/core/protocol/client_response.hxx +1 -0
  154. data/ext/couchbase/core/protocol/cmd_hello.hxx +1 -0
  155. data/ext/couchbase/core/protocol/cmd_lookup_in_replica.cxx +107 -0
  156. data/ext/couchbase/core/protocol/cmd_lookup_in_replica.hxx +137 -0
  157. data/ext/couchbase/core/protocol/hello_feature.hxx +6 -0
  158. data/ext/couchbase/core/protocol/hello_feature_fmt.hxx +3 -0
  159. data/ext/couchbase/core/protocol/status.cxx +2 -2
  160. data/ext/couchbase/core/public_fwd.hxx +21 -0
  161. data/ext/couchbase/core/range_scan_options.cxx +3 -27
  162. data/ext/couchbase/core/range_scan_options.hxx +13 -17
  163. data/ext/couchbase/core/range_scan_orchestrator.cxx +388 -170
  164. data/ext/couchbase/core/range_scan_orchestrator.hxx +13 -2
  165. data/ext/couchbase/core/range_scan_orchestrator_options.hxx +5 -3
  166. data/ext/couchbase/core/scan_options.hxx +0 -19
  167. data/ext/couchbase/core/scan_result.cxx +19 -5
  168. data/ext/couchbase/core/scan_result.hxx +5 -2
  169. data/ext/couchbase/core/timeout_defaults.hxx +2 -3
  170. data/ext/couchbase/core/tls_verify_mode.hxx +26 -0
  171. data/ext/couchbase/core/topology/capabilities.hxx +3 -0
  172. data/ext/couchbase/core/topology/capabilities_fmt.hxx +8 -0
  173. data/ext/couchbase/core/topology/collections_manifest_fmt.hxx +1 -1
  174. data/ext/couchbase/core/topology/configuration.cxx +15 -2
  175. data/ext/couchbase/core/topology/configuration.hxx +20 -1
  176. data/ext/couchbase/core/topology/configuration_json.hxx +6 -1
  177. data/ext/couchbase/core/transactions/attempt_context_testing_hooks.cxx +93 -0
  178. data/ext/couchbase/core/transactions/attempt_context_testing_hooks.hxx +48 -75
  179. data/ext/couchbase/core/transactions/cleanup_testing_hooks.cxx +52 -0
  180. data/ext/couchbase/core/transactions/cleanup_testing_hooks.hxx +17 -31
  181. data/ext/couchbase/core/transactions/exceptions.hxx +12 -9
  182. data/ext/couchbase/core/utils/connection_string.cxx +75 -43
  183. data/ext/couchbase/core/utils/connection_string.hxx +1 -0
  184. data/ext/couchbase/core/utils/json.cxx +4 -1
  185. data/ext/couchbase/couchbase/analytics_error_context.hxx +1 -1
  186. data/ext/couchbase/couchbase/behavior_options.hxx +27 -1
  187. data/ext/couchbase/couchbase/boolean_field_query.hxx +77 -0
  188. data/ext/couchbase/couchbase/boolean_query.hxx +223 -0
  189. data/ext/couchbase/couchbase/bucket_manager.hxx +135 -0
  190. data/ext/couchbase/couchbase/build_query_index_options.hxx +0 -30
  191. data/ext/couchbase/couchbase/cluster.hxx +56 -1
  192. data/ext/couchbase/couchbase/collection.hxx +111 -0
  193. data/ext/couchbase/couchbase/collection_query_index_manager.hxx +7 -48
  194. data/ext/couchbase/couchbase/conjunction_query.hxx +88 -0
  195. data/ext/couchbase/couchbase/create_bucket_options.hxx +41 -0
  196. data/ext/couchbase/couchbase/create_primary_query_index_options.hxx +0 -29
  197. data/ext/couchbase/couchbase/create_query_index_options.hxx +0 -33
  198. data/ext/couchbase/couchbase/date_range.hxx +69 -0
  199. data/ext/couchbase/couchbase/date_range_facet.hxx +56 -0
  200. data/ext/couchbase/couchbase/date_range_facet_result.hxx +55 -0
  201. data/ext/couchbase/couchbase/date_range_query.hxx +265 -0
  202. data/ext/couchbase/couchbase/disjunction_query.hxx +109 -0
  203. data/ext/couchbase/couchbase/doc_id_query.hxx +111 -0
  204. data/ext/couchbase/couchbase/drop_bucket_options.hxx +41 -0
  205. data/ext/couchbase/couchbase/drop_primary_query_index_options.hxx +0 -30
  206. data/ext/couchbase/couchbase/drop_query_index_options.hxx +0 -31
  207. data/ext/couchbase/couchbase/error_codes.hxx +1 -2
  208. data/ext/couchbase/couchbase/error_context.hxx +17 -8
  209. data/ext/couchbase/couchbase/flush_bucket_options.hxx +41 -0
  210. data/ext/couchbase/couchbase/fmt/analytics_scan_consistency.hxx +52 -0
  211. data/ext/couchbase/{core/topology/error_map_fmt.hxx → couchbase/fmt/key_value_error_map_attribute.hxx} +21 -21
  212. data/ext/couchbase/couchbase/fmt/search_scan_consistency.hxx +49 -0
  213. data/ext/couchbase/couchbase/geo_bounding_box_query.hxx +107 -0
  214. data/ext/couchbase/couchbase/geo_distance_query.hxx +109 -0
  215. data/ext/couchbase/couchbase/geo_point.hxx +32 -0
  216. data/ext/couchbase/couchbase/geo_polygon_query.hxx +85 -0
  217. data/ext/couchbase/couchbase/get_all_buckets_options.hxx +44 -0
  218. data/ext/couchbase/couchbase/get_all_query_indexes_options.hxx +0 -30
  219. data/ext/couchbase/couchbase/get_and_lock_options.hxx +2 -2
  220. data/ext/couchbase/couchbase/get_and_touch_options.hxx +2 -2
  221. data/ext/couchbase/couchbase/get_bucket_options.hxx +43 -0
  222. data/ext/couchbase/couchbase/get_options.hxx +2 -2
  223. data/ext/couchbase/couchbase/highlight_style.hxx +45 -0
  224. data/ext/couchbase/couchbase/insert_options.hxx +3 -3
  225. data/ext/couchbase/couchbase/key_value_error_context.hxx +7 -2
  226. data/ext/couchbase/couchbase/lookup_in_all_replicas_options.hxx +109 -0
  227. data/ext/couchbase/couchbase/lookup_in_any_replica_options.hxx +101 -0
  228. data/ext/couchbase/couchbase/lookup_in_options.hxx +2 -2
  229. data/ext/couchbase/couchbase/lookup_in_replica_result.hxx +74 -0
  230. data/ext/couchbase/couchbase/lookup_in_result.hxx +26 -0
  231. data/ext/couchbase/couchbase/management/bucket_settings.hxx +116 -0
  232. data/ext/couchbase/couchbase/manager_error_context.hxx +29 -53
  233. data/ext/couchbase/couchbase/match_all_query.hxx +43 -0
  234. data/ext/couchbase/couchbase/match_none_query.hxx +43 -0
  235. data/ext/couchbase/couchbase/match_operator.hxx +45 -0
  236. data/ext/couchbase/couchbase/match_phrase_query.hxx +108 -0
  237. data/ext/couchbase/couchbase/match_query.hxx +163 -0
  238. data/ext/couchbase/couchbase/mutate_in_options.hxx +2 -2
  239. data/ext/couchbase/couchbase/numeric_range.hxx +58 -0
  240. data/ext/couchbase/couchbase/numeric_range_facet.hxx +56 -0
  241. data/ext/couchbase/couchbase/numeric_range_facet_result.hxx +55 -0
  242. data/ext/couchbase/couchbase/numeric_range_query.hxx +143 -0
  243. data/ext/couchbase/couchbase/phrase_query.hxx +93 -0
  244. data/ext/couchbase/couchbase/prefix_query.hxx +82 -0
  245. data/ext/couchbase/couchbase/query_error_context.hxx +3 -1
  246. data/ext/couchbase/couchbase/query_index_manager.hxx +16 -83
  247. data/ext/couchbase/couchbase/query_options.hxx +18 -0
  248. data/ext/couchbase/couchbase/query_string_query.hxx +72 -0
  249. data/ext/couchbase/couchbase/regexp_query.hxx +82 -0
  250. data/ext/couchbase/couchbase/remove_options.hxx +2 -2
  251. data/ext/couchbase/couchbase/replace_options.hxx +3 -3
  252. data/ext/couchbase/couchbase/scope.hxx +40 -0
  253. data/ext/couchbase/couchbase/search_date_range.hxx +68 -0
  254. data/ext/couchbase/couchbase/search_error_context.hxx +138 -0
  255. data/ext/couchbase/couchbase/search_facet.hxx +60 -0
  256. data/ext/couchbase/couchbase/search_facet_result.hxx +50 -0
  257. data/ext/couchbase/couchbase/search_meta_data.hxx +85 -0
  258. data/ext/couchbase/couchbase/search_metrics.hxx +127 -0
  259. data/ext/couchbase/couchbase/search_numeric_range.hxx +69 -0
  260. data/ext/couchbase/couchbase/search_options.hxx +509 -0
  261. data/ext/couchbase/couchbase/search_query.hxx +69 -0
  262. data/ext/couchbase/couchbase/search_result.hxx +77 -0
  263. data/ext/couchbase/couchbase/search_row.hxx +104 -0
  264. data/ext/couchbase/couchbase/search_row_location.hxx +55 -0
  265. data/ext/couchbase/couchbase/search_row_locations.hxx +86 -0
  266. data/ext/couchbase/couchbase/search_scan_consistency.hxx +34 -0
  267. data/ext/couchbase/couchbase/search_sort.hxx +58 -0
  268. data/ext/couchbase/couchbase/search_sort_field.hxx +117 -0
  269. data/ext/couchbase/couchbase/search_sort_field_missing.hxx +26 -0
  270. data/ext/couchbase/couchbase/search_sort_field_mode.hxx +27 -0
  271. data/ext/couchbase/couchbase/search_sort_field_type.hxx +28 -0
  272. data/ext/couchbase/couchbase/search_sort_id.hxx +60 -0
  273. data/ext/couchbase/couchbase/search_sort_score.hxx +60 -0
  274. data/ext/couchbase/couchbase/search_term_range.hxx +51 -0
  275. data/ext/couchbase/couchbase/security_options.hxx +18 -0
  276. data/ext/couchbase/couchbase/subdocument_error_context.hxx +4 -2
  277. data/ext/couchbase/couchbase/term_facet.hxx +48 -0
  278. data/ext/couchbase/couchbase/term_facet_result.hxx +55 -0
  279. data/ext/couchbase/couchbase/term_query.hxx +151 -0
  280. data/ext/couchbase/couchbase/term_range_query.hxx +142 -0
  281. data/ext/couchbase/couchbase/touch_options.hxx +2 -2
  282. data/ext/couchbase/couchbase/tracing/request_span.hxx +63 -0
  283. data/ext/couchbase/couchbase/tracing/request_tracer.hxx +2 -40
  284. data/ext/couchbase/couchbase/transactions/async_attempt_context.hxx +83 -4
  285. data/ext/couchbase/couchbase/transactions/attempt_context.hxx +67 -0
  286. data/ext/couchbase/couchbase/transactions/transaction_get_result.hxx +2 -0
  287. data/ext/couchbase/couchbase/transactions/transaction_keyspace.hxx +11 -1
  288. data/ext/couchbase/couchbase/transactions/transaction_options.hxx +79 -8
  289. data/ext/couchbase/couchbase/transactions/transaction_query_options.hxx +128 -15
  290. data/ext/couchbase/couchbase/transactions/transaction_query_result.hxx +4 -0
  291. data/ext/couchbase/couchbase/transactions/transaction_result.hxx +1 -1
  292. data/ext/couchbase/couchbase/transactions/transactions_cleanup_config.hxx +5 -3
  293. data/ext/couchbase/couchbase/transactions/transactions_config.hxx +9 -5
  294. data/ext/couchbase/couchbase/transactions/transactions_query_config.hxx +6 -3
  295. data/ext/couchbase/couchbase/transactions.hxx +34 -1
  296. data/ext/couchbase/couchbase/unlock_options.hxx +2 -2
  297. data/ext/couchbase/couchbase/update_bucket_options.hxx +41 -0
  298. data/ext/couchbase/couchbase/upsert_options.hxx +3 -3
  299. data/ext/couchbase/couchbase/watch_query_indexes_options.hxx +0 -31
  300. data/ext/couchbase/couchbase/wildcard_query.hxx +83 -0
  301. data/ext/couchbase/test/CMakeLists.txt +8 -5
  302. data/ext/couchbase/test/benchmark_helper_integration.hxx +2 -2
  303. data/ext/couchbase/test/test_helper.hxx +5 -5
  304. data/ext/couchbase/test/test_integration_analytics.cxx +28 -6
  305. data/ext/couchbase/test/test_integration_collections.cxx +13 -3
  306. data/ext/couchbase/test/test_integration_connect.cxx +7 -3
  307. data/ext/couchbase/test/test_integration_crud.cxx +18 -3
  308. data/ext/couchbase/test/test_integration_diagnostics.cxx +11 -5
  309. data/ext/couchbase/test/test_integration_durability.cxx +12 -7
  310. data/ext/couchbase/test/test_integration_examples.cxx +419 -11
  311. data/ext/couchbase/test/test_integration_management.cxx +867 -368
  312. data/ext/couchbase/test/test_integration_query.cxx +87 -17
  313. data/ext/couchbase/test/test_integration_range_scan.cxx +363 -124
  314. data/ext/couchbase/test/test_integration_read_replica.cxx +48 -11
  315. data/ext/couchbase/test/test_integration_search.cxx +32 -3
  316. data/ext/couchbase/test/test_integration_subdoc.cxx +717 -11
  317. data/ext/couchbase/test/test_integration_tracer.cxx +5 -0
  318. data/ext/couchbase/test/test_integration_transcoders.cxx +13 -5
  319. data/ext/couchbase/test/{test_transaction_transaction_context.cxx → test_transaction_context.cxx} +1 -1
  320. data/ext/couchbase/test/test_transaction_examples.cxx +195 -0
  321. data/ext/couchbase/test/{test_transaction_transaction_public_async_api.cxx → test_transaction_public_async_api.cxx} +13 -12
  322. data/ext/couchbase/test/{test_transaction_transaction_public_blocking_api.cxx → test_transaction_public_blocking_api.cxx} +27 -21
  323. data/ext/couchbase/test/{test_transaction_transaction_simple.cxx → test_transaction_simple.cxx} +17 -5
  324. data/ext/couchbase/test/{test_transaction_transaction_simple_async.cxx → test_transaction_simple_async.cxx} +19 -21
  325. data/ext/couchbase/test/test_unit_config_profiles.cxx +1 -1
  326. data/ext/couchbase/test/test_unit_connection_string.cxx +29 -0
  327. data/ext/couchbase/test/test_unit_json_transcoder.cxx +4 -0
  328. data/ext/couchbase/test/test_unit_query.cxx +75 -0
  329. data/ext/couchbase/test/test_unit_search.cxx +427 -0
  330. data/ext/couchbase/test/test_unit_transaction_utils.cxx +10 -1
  331. data/ext/couchbase/test/test_unit_utils.cxx +8 -4
  332. data/ext/couchbase.cxx +641 -45
  333. data/ext/revisions.rb +3 -3
  334. data/lib/couchbase/authenticator.rb +0 -1
  335. data/lib/couchbase/cluster.rb +1 -5
  336. data/lib/couchbase/collection.rb +108 -0
  337. data/lib/couchbase/collection_options.rb +100 -0
  338. data/lib/couchbase/config_profiles.rb +1 -1
  339. data/lib/couchbase/errors.rb +5 -0
  340. data/lib/couchbase/json_transcoder.rb +12 -5
  341. data/lib/couchbase/key_value_scan.rb +125 -0
  342. data/lib/couchbase/management/collection_query_index_manager.rb +54 -15
  343. data/lib/couchbase/management/query_index_manager.rb +70 -5
  344. data/lib/couchbase/options.rb +151 -0
  345. data/lib/couchbase/raw_binary_transcoder.rb +37 -0
  346. data/lib/couchbase/raw_json_transcoder.rb +38 -0
  347. data/lib/couchbase/raw_string_transcoder.rb +40 -0
  348. data/lib/couchbase/scope.rb +1 -1
  349. data/lib/couchbase/search_options.rb +5 -0
  350. data/lib/couchbase/transcoder_flags.rb +62 -0
  351. data/lib/couchbase/utils/time.rb +14 -1
  352. data/lib/couchbase/version.rb +1 -1
  353. metadata +175 -13
  354. data/ext/couchbase/core/config_profile.cxx +0 -47
  355. data/ext/couchbase/core/impl/collection_query_index_manager.cxx +0 -93
@@ -72,7 +72,7 @@ class collection_cache
72
72
  if (auto ptr = cid_map_.find(path); ptr != cid_map_.end()) {
73
73
  return ptr->second;
74
74
  }
75
- return {};
75
+ return std::nullopt;
76
76
  }
77
77
 
78
78
  void update(const std::string& path, std::uint32_t id)
@@ -379,7 +379,17 @@ class mcbp_session_impl
379
379
  Expects(protocol::is_valid_server_request_opcode(msg.header.opcode));
380
380
  switch (static_cast<protocol::server_opcode>(msg.header.opcode)) {
381
381
  case protocol::server_opcode::cluster_map_change_notification: {
382
- protocol::cmd_info info{ session_->endpoint_address_, session_->endpoint_.port() };
382
+ protocol::cmd_info info{ session_->bootstrap_hostname_, session_->bootstrap_port_number_ };
383
+ if (session_->origin_.options().dump_configuration) {
384
+ std::string_view config_text{ reinterpret_cast<const char*>(msg.body.data()), msg.body.size() };
385
+ CB_LOG_TRACE(
386
+ "{} configuration from cluster_map_change_notification request (size={}, endpoint=\"{}:{}\"), {}",
387
+ session_->log_prefix_,
388
+ config_text.size(),
389
+ info.endpoint_address,
390
+ info.endpoint_port,
391
+ config_text);
392
+ }
383
393
  protocol::server_request<protocol::cluster_map_change_notification_request_body> req(std::move(msg), info);
384
394
  std::optional<topology::configuration> config = req.body().config();
385
395
  if (session_ && config.has_value()) {
@@ -394,7 +404,7 @@ class mcbp_session_impl
394
404
  CB_LOG_WARNING("{} unexpected server request: opcode={:x}, opaque={}{:a}{:a}",
395
405
  session_->log_prefix_,
396
406
  msg.header.opcode,
397
- msg.header.opaque,
407
+ utils::byte_swap(msg.header.opaque),
398
408
  spdlog::to_hex(msg.header_data()),
399
409
  spdlog::to_hex(msg.body));
400
410
  }
@@ -406,7 +416,7 @@ class mcbp_session_impl
406
416
  session_->log_prefix_,
407
417
  magic,
408
418
  msg.header.opcode,
409
- msg.header.opaque,
419
+ utils::byte_swap(msg.header.opaque),
410
420
  spdlog::to_hex(msg.header_data()),
411
421
  spdlog::to_hex(msg.body));
412
422
  break;
@@ -463,7 +473,16 @@ class mcbp_session_impl
463
473
  Expects(protocol::is_valid_client_opcode(msg.header.opcode));
464
474
  switch (auto opcode = static_cast<protocol::client_opcode>(msg.header.opcode)) {
465
475
  case protocol::client_opcode::get_cluster_config: {
466
- protocol::cmd_info info{ session_->endpoint_address_, session_->endpoint_.port() };
476
+ protocol::cmd_info info{ session_->bootstrap_hostname_, session_->bootstrap_port_number_ };
477
+ if (session_->origin_.options().dump_configuration) {
478
+ std::string_view config_text{ reinterpret_cast<const char*>(msg.body.data()), msg.body.size() };
479
+ CB_LOG_TRACE("{} configuration from get_cluster_config response (size={}, endpoint=\"{}:{}\"), {}",
480
+ session_->log_prefix_,
481
+ config_text.size(),
482
+ info.endpoint_address,
483
+ info.endpoint_port,
484
+ config_text);
485
+ }
467
486
  protocol::client_response<protocol::get_cluster_config_response_body> resp(std::move(msg), info);
468
487
  if (resp.status() == key_value_status_code::success) {
469
488
  if (session_) {
@@ -762,13 +781,10 @@ class mcbp_session_impl
762
781
  return;
763
782
  }
764
783
  std::tie(bootstrap_hostname_, bootstrap_port_) = origin_.next_address();
765
- log_prefix_ = fmt::format("[{}/{}/{}/{}] <{}:{}>",
766
- client_id_,
767
- id_,
768
- stream_->log_prefix(),
769
- bucket_name_.value_or("-"),
770
- bootstrap_hostname_,
771
- bootstrap_port_);
784
+ bootstrap_port_number_ = gsl::narrow_cast<std::uint16_t>(std::stoul(bootstrap_port_, nullptr, 10));
785
+ bootstrap_address_ = fmt::format("{}:{}", bootstrap_hostname_, bootstrap_port_);
786
+ log_prefix_ =
787
+ fmt::format("[{}/{}/{}/{}] <{}>", client_id_, id_, stream_->log_prefix(), bucket_name_.value_or("-"), bootstrap_address_);
772
788
  CB_LOG_DEBUG("{} attempt to establish MCBP connection", log_prefix_);
773
789
 
774
790
  async_resolve(origin_.options().use_ip_protocol,
@@ -788,7 +804,7 @@ class mcbp_session_impl
788
804
  return stopped_;
789
805
  }
790
806
 
791
- void on_stop(utils::movable_function<void(retry_reason)> handler)
807
+ void on_stop(utils::movable_function<void()> handler)
792
808
  {
793
809
  on_stop_handler_ = std::move(handler);
794
810
  }
@@ -844,7 +860,7 @@ class mcbp_session_impl
844
860
  config_listeners_.clear();
845
861
  state_ = diag::endpoint_state::disconnected;
846
862
  if (auto on_stop = std::move(on_stop_handler_); on_stop) {
847
- on_stop(reason);
863
+ on_stop();
848
864
  }
849
865
  }
850
866
 
@@ -855,7 +871,7 @@ class mcbp_session_impl
855
871
  }
856
872
  std::uint32_t opaque{ 0 };
857
873
  std::memcpy(&opaque, buf.data() + 12, sizeof(opaque));
858
- CB_LOG_TRACE("{} MCBP send, opaque={}, {:n}", log_prefix_, opaque, spdlog::to_hex(buf.begin(), buf.begin() + 24));
874
+ CB_LOG_TRACE("{} MCBP send, opaque={}, {:n}", log_prefix_, utils::byte_swap(opaque), spdlog::to_hex(buf.begin(), buf.begin() + 24));
859
875
  std::scoped_lock lock(output_buffer_mutex_);
860
876
  output_buffer_.emplace_back(std::move(buf));
861
877
  }
@@ -1039,6 +1055,11 @@ class mcbp_session_impl
1039
1055
  return config_->index_for_this_node();
1040
1056
  }
1041
1057
 
1058
+ [[nodiscard]] const std::string& bootstrap_address() const
1059
+ {
1060
+ return bootstrap_address_;
1061
+ }
1062
+
1042
1063
  [[nodiscard]] const std::string& bootstrap_hostname() const
1043
1064
  {
1044
1065
  return bootstrap_hostname_;
@@ -1049,6 +1070,11 @@ class mcbp_session_impl
1049
1070
  return bootstrap_port_;
1050
1071
  }
1051
1072
 
1073
+ [[nodiscard]] std::uint16_t bootstrap_port_number() const
1074
+ {
1075
+ return bootstrap_port_number_;
1076
+ }
1077
+
1052
1078
  [[nodiscard]] std::uint32_t next_opaque()
1053
1079
  {
1054
1080
  return ++opaque_;
@@ -1138,11 +1164,19 @@ class mcbp_session_impl
1138
1164
  if (utils::byte_swap(msg.header.bodylen) - offset > 0) {
1139
1165
  std::string_view config_text{ reinterpret_cast<const char*>(msg.body.data()) + offset,
1140
1166
  msg.body.size() - static_cast<std::size_t>(offset) };
1141
- auto config = protocol::parse_config(config_text, endpoint_address_, endpoint_.port());
1167
+ if (origin_.options().dump_configuration) {
1168
+ CB_LOG_TRACE("{} configuration from not_my_vbucket response (size={}, endpoint=\"{}:{}\"), {}",
1169
+ log_prefix_,
1170
+ config_text.size(),
1171
+ bootstrap_hostname_,
1172
+ bootstrap_port_number_,
1173
+ config_text);
1174
+ }
1175
+ auto config = protocol::parse_config(config_text, bootstrap_hostname_, bootstrap_port_number_);
1142
1176
  CB_LOG_DEBUG("{} received not_my_vbucket status for {}, opaque={} with config rev={} in the payload",
1143
1177
  log_prefix_,
1144
1178
  protocol::client_opcode(msg.header.opcode),
1145
- msg.header.opaque,
1179
+ utils::byte_swap(msg.header.opaque),
1146
1180
  config.rev_str());
1147
1181
  update_configuration(std::move(config));
1148
1182
  }
@@ -1177,6 +1211,12 @@ class mcbp_session_impl
1177
1211
  CB_LOG_DEBUG(R"({} server returned {} ({}), it must be transient condition, retrying)", log_prefix_, ec.value(), ec.message());
1178
1212
  return initiate_bootstrap();
1179
1213
  }
1214
+ if (!origin_.exhausted() && ec == errc::common::authentication_failure) {
1215
+ CB_LOG_DEBUG(
1216
+ R"({} server returned authentication_failure, but the bootstrap list is not exhausted yet. It must be transient condition, retrying)",
1217
+ log_prefix_);
1218
+ return initiate_bootstrap();
1219
+ }
1180
1220
 
1181
1221
  if (!bootstrapped_ && bootstrap_callback_) {
1182
1222
  bootstrap_deadline_.cancel();
@@ -1239,16 +1279,15 @@ class mcbp_session_impl
1239
1279
  }
1240
1280
  last_active_ = std::chrono::steady_clock::now();
1241
1281
  if (it != endpoints_.end()) {
1242
- CB_LOG_DEBUG("{} connecting to {}:{}, timeout={}ms",
1243
- log_prefix_,
1244
- it->endpoint().address().to_string(),
1245
- it->endpoint().port(),
1246
- origin_.options().connect_timeout.count());
1282
+ auto hostname = it->endpoint().address().to_string();
1283
+ auto port = it->endpoint().port();
1284
+ CB_LOG_DEBUG("{} connecting to {}:{}, timeout={}ms", log_prefix_, hostname, port, origin_.options().connect_timeout.count());
1247
1285
  connection_deadline_.expires_after(origin_.options().connect_timeout);
1248
- connection_deadline_.async_wait([self = shared_from_this()](const auto timer_ec) {
1286
+ connection_deadline_.async_wait([self = shared_from_this(), hostname, port](const auto timer_ec) {
1249
1287
  if (timer_ec == asio::error::operation_aborted || self->stopped_) {
1250
1288
  return;
1251
1289
  }
1290
+ CB_LOG_DEBUG("{} unable to connect to {}:{} in time, reconnecting", self->log_prefix_, hostname, port);
1252
1291
  return self->stream_->close([self](std::error_code) { self->initiate_bootstrap(); });
1253
1292
  });
1254
1293
  stream_->async_connect(it->endpoint(),
@@ -1326,7 +1365,20 @@ class mcbp_session_impl
1326
1365
  asio::buffer(input_buffer_),
1327
1366
  [self = shared_from_this(), stream_id = stream_->id()](std::error_code ec, std::size_t bytes_transferred) {
1328
1367
  if (ec == asio::error::operation_aborted || self->stopped_) {
1368
+ CB_LOG_PROTOCOL("[MCBP, IN] host=\"{}\", port={}, rc={}, bytes_received={}",
1369
+ self->endpoint_address_,
1370
+ self->endpoint_.port(),
1371
+ ec ? ec.message() : "ok",
1372
+ bytes_transferred);
1329
1373
  return;
1374
+ } else {
1375
+ CB_LOG_PROTOCOL("[MCBP, IN] host=\"{}\", port={}, rc={}, bytes_received={}{:a}",
1376
+ self->endpoint_address_,
1377
+ self->endpoint_.port(),
1378
+ ec ? ec.message() : "ok",
1379
+ bytes_transferred,
1380
+ spdlog::to_hex(self->input_buffer_.data(),
1381
+ self->input_buffer_.data() + static_cast<std::ptrdiff_t>(bytes_transferred)));
1330
1382
  }
1331
1383
  self->last_active_ = std::chrono::steady_clock::now();
1332
1384
  if (ec) {
@@ -1355,8 +1407,10 @@ class mcbp_session_impl
1355
1407
  if (self->stopped_) {
1356
1408
  return;
1357
1409
  }
1358
- CB_LOG_TRACE(
1359
- "{} MCBP recv, opaque={}, {:n}", self->log_prefix_, msg.header.opaque, spdlog::to_hex(msg.header_data()));
1410
+ CB_LOG_TRACE("{} MCBP recv, opaque={}, {:n}",
1411
+ self->log_prefix_,
1412
+ utils::byte_swap(msg.header.opaque),
1413
+ spdlog::to_hex(msg.header_data()));
1360
1414
  if (self->bootstrapped_) {
1361
1415
  self->handler_->handle(std::move(msg));
1362
1416
  } else {
@@ -1392,13 +1446,21 @@ class mcbp_session_impl
1392
1446
  std::vector<asio::const_buffer> buffers;
1393
1447
  buffers.reserve(writing_buffer_.size());
1394
1448
  for (auto& buf : writing_buffer_) {
1449
+ CB_LOG_PROTOCOL(
1450
+ "[MCBP, OUT] host=\"{}\", port={}, buffer_size={}{:a}", endpoint_address_, endpoint_.port(), buf.size(), spdlog::to_hex(buf));
1395
1451
  buffers.emplace_back(asio::buffer(buf));
1396
1452
  }
1397
- stream_->async_write(buffers, [self = shared_from_this()](std::error_code ec, std::size_t /*unused*/) {
1453
+ stream_->async_write(buffers, [self = shared_from_this()](std::error_code ec, std::size_t bytes_transferred) {
1454
+ CB_LOG_PROTOCOL("[MCBP, OUT] host=\"{}\", port={}, rc={}, bytes_sent={}",
1455
+ self->endpoint_address_,
1456
+ self->endpoint_.port(),
1457
+ ec ? ec.message() : "ok",
1458
+ bytes_transferred);
1398
1459
  if (ec == asio::error::operation_aborted || self->stopped_) {
1399
1460
  return;
1400
1461
  }
1401
1462
  self->last_active_ = std::chrono::steady_clock::now();
1463
+
1402
1464
  if (ec) {
1403
1465
  CB_LOG_ERROR(R"({} IO error while writing to the socket("{}"): {} ({}))",
1404
1466
  self->log_prefix_,
@@ -1435,7 +1497,7 @@ class mcbp_session_impl
1435
1497
  std::mutex command_handlers_mutex_{};
1436
1498
  std::map<std::uint32_t, command_handler> command_handlers_{};
1437
1499
  std::vector<std::shared_ptr<config_listener>> config_listeners_{};
1438
- utils::movable_function<void(retry_reason)> on_stop_handler_{};
1500
+ utils::movable_function<void()> on_stop_handler_{};
1439
1501
 
1440
1502
  std::atomic_bool bootstrapped_{ false };
1441
1503
  std::atomic_bool stopped_{ false };
@@ -1455,6 +1517,8 @@ class mcbp_session_impl
1455
1517
  std::mutex writing_buffer_mutex_{};
1456
1518
  std::string bootstrap_hostname_{};
1457
1519
  std::string bootstrap_port_{};
1520
+ std::string bootstrap_address_{};
1521
+ std::uint16_t bootstrap_port_number_{};
1458
1522
  asio::ip::tcp::endpoint endpoint_{}; // connected endpoint
1459
1523
  std::string endpoint_address_{}; // cached string with endpoint address
1460
1524
  asio::ip::tcp::endpoint local_endpoint_{};
@@ -1555,22 +1619,16 @@ mcbp_session::supports_feature(protocol::hello_feature feature)
1555
1619
  return impl_->supports_feature(feature);
1556
1620
  }
1557
1621
 
1558
- // const std::string&
1559
- // mcbp_session::id() const
1560
- // {
1561
- // return impl_->id();
1562
- // }
1563
- std::string
1622
+ const std::string&
1564
1623
  mcbp_session::id() const
1565
1624
  {
1566
- if (impl_) {
1567
- return fmt::format("{}, {}, {}, refcnt={}",
1568
- reinterpret_cast<const void*>(this),
1569
- reinterpret_cast<const void*>(impl_.get()),
1570
- impl_->id(),
1571
- impl_.use_count());
1572
- }
1573
- return fmt::format("{}, nullptr", reinterpret_cast<const void*>(this));
1625
+ return impl_->id();
1626
+ }
1627
+
1628
+ const std::string&
1629
+ mcbp_session::bootstrap_address() const
1630
+ {
1631
+ return impl_->bootstrap_address();
1574
1632
  }
1575
1633
 
1576
1634
  std::string
@@ -1597,6 +1655,12 @@ mcbp_session::bootstrap_port() const
1597
1655
  return impl_->bootstrap_port();
1598
1656
  }
1599
1657
 
1658
+ std::uint16_t
1659
+ mcbp_session::bootstrap_port_number() const
1660
+ {
1661
+ return impl_->bootstrap_port_number();
1662
+ }
1663
+
1600
1664
  void
1601
1665
  mcbp_session::write_and_subscribe(std::uint32_t opaque, std::vector<std::byte>&& data, command_handler&& handler)
1602
1666
  {
@@ -1610,7 +1674,7 @@ mcbp_session::bootstrap(utils::movable_function<void(std::error_code, topology::
1610
1674
  }
1611
1675
 
1612
1676
  void
1613
- mcbp_session::on_stop(utils::movable_function<void(retry_reason)> handler)
1677
+ mcbp_session::on_stop(utils::movable_function<void()> handler)
1614
1678
  {
1615
1679
  return impl_->on_stop(std::move(handler));
1616
1680
  }
@@ -101,17 +101,18 @@ class mcbp_session
101
101
  [[nodiscard]] mcbp_context context() const;
102
102
  [[nodiscard]] bool supports_feature(protocol::hello_feature feature);
103
103
  [[nodiscard]] std::vector<protocol::hello_feature> supported_features() const;
104
- //[[nodiscard]] const std::string& id() const;
105
- [[nodiscard]] std::string id() const;
104
+ [[nodiscard]] const std::string& id() const;
106
105
  [[nodiscard]] std::string remote_address() const;
107
106
  [[nodiscard]] std::string local_address() const;
107
+ [[nodiscard]] const std::string& bootstrap_address() const;
108
108
  [[nodiscard]] const std::string& bootstrap_hostname() const;
109
109
  [[nodiscard]] const std::string& bootstrap_port() const;
110
+ [[nodiscard]] std::uint16_t bootstrap_port_number() const;
110
111
  void write_and_subscribe(std::shared_ptr<mcbp::queue_request>, std::shared_ptr<response_handler> handler);
111
112
  void write_and_subscribe(std::uint32_t opaque, std::vector<std::byte>&& data, command_handler&& handler);
112
113
  void bootstrap(utils::movable_function<void(std::error_code, topology::configuration)>&& handler,
113
114
  bool retry_on_bucket_not_found = false);
114
- void on_stop(utils::movable_function<void(retry_reason)> handler);
115
+ void on_stop(utils::movable_function<void()> handler);
115
116
  void stop(retry_reason reason);
116
117
  [[nodiscard]] std::size_t index() const;
117
118
  [[nodiscard]] bool has_config() const;
@@ -55,13 +55,14 @@ retry_with_duration(std::shared_ptr<Manager> manager,
55
55
  std::chrono::milliseconds duration)
56
56
  {
57
57
  command->request.retries.record_retry_attempt(reason);
58
- CB_LOG_TRACE(R"({} retrying operation {} (duration={}ms, id="{}", reason={}, attempts={}))",
58
+ CB_LOG_TRACE(R"({} retrying operation {} (duration={}ms, id="{}", reason={}, attempts={}, last_dispatched_to=\"{}\"))",
59
59
  manager->log_prefix(),
60
60
  decltype(command->request)::encoded_request_type::body_type::opcode,
61
61
  duration.count(),
62
62
  command->id_,
63
63
  reason,
64
- command->request.retries.retry_attempts());
64
+ command->request.retries.retry_attempts(),
65
+ command->session_ ? command->session_->remote_address() : "");
65
66
  manager->schedule_for_retry(command, duration);
66
67
  }
67
68
 
@@ -37,6 +37,11 @@ struct json_string {
37
37
  return *this;
38
38
  }
39
39
 
40
+ json_string(const std::vector<std::byte>& value)
41
+ : value_(value)
42
+ {
43
+ }
44
+
40
45
  json_string(std::vector<std::byte>&& value)
41
46
  : value_(std::move(value))
42
47
  {
@@ -127,7 +127,7 @@ custom_rotating_file_sink<Mutex>::add_hook(const std::string& hook)
127
127
 
128
128
  // Payload shouldn't contain anything yet, overwrite it
129
129
  Expects(msg.payload.size() == 0);
130
- msg.payload = hook;
130
+ msg.payload = hookToAdd;
131
131
 
132
132
  spdlog::memory_buf_t formatted;
133
133
  formatter->format(msg, formatted);
@@ -22,7 +22,8 @@
22
22
  #include <spdlog/sinks/stdout_color_sinks.h>
23
23
  #include <spdlog/spdlog.h>
24
24
 
25
- static const std::string logger_name{ "couchbase_cxx_client_file_logger" };
25
+ static const std::string file_logger_name{ "couchbase_cxx_client_file_logger" };
26
+ static const std::string protocol_logger_name{ "couchbase_cxx_client_protocol_logger" };
26
27
 
27
28
  /**
28
29
  * Custom log pattern which the loggers will use.
@@ -39,7 +40,12 @@ static const std::string log_pattern{ "[%Y-%m-%d %T.%e] [%P,%t] [%^%l%$] %oms, %
39
40
  * messages and send them to the sinks, which do the actual writing (to file,
40
41
  * to stream etc.) or further processing.
41
42
  */
42
- static std::shared_ptr<spdlog::logger> file_logger;
43
+ static std::shared_ptr<spdlog::logger> file_logger{};
44
+
45
+ /**
46
+ * Instance of the protocol logger.
47
+ */
48
+ static std::shared_ptr<spdlog::logger> protocol_logger{};
43
49
 
44
50
  namespace couchbase::core::logger
45
51
  {
@@ -146,13 +152,11 @@ is_initialized()
146
152
  return file_logger != nullptr;
147
153
  }
148
154
 
149
- /**
150
- * Initialises the loggers. Called if the logger configuration is
151
- * specified in a separate settings object.
152
- */
153
- std::optional<std::string>
154
- create_file_logger(const configuration& logger_settings)
155
+ std::pair<std::optional<std::string>, std::shared_ptr<spdlog::logger>>
156
+ create_file_logger_impl(const std::string logger_name, const configuration& logger_settings)
155
157
  {
158
+ std::shared_ptr<spdlog::logger> logger{};
159
+
156
160
  auto fname = logger_settings.filename;
157
161
  auto buffersz = logger_settings.buffer_size;
158
162
  auto cyclesz = logger_settings.cycle_size;
@@ -218,7 +222,7 @@ create_file_logger(const configuration& logger_settings)
218
222
  spdlog::drop(logger_name);
219
223
 
220
224
  if (logger_settings.unit_test) {
221
- file_logger = std::make_shared<spdlog::logger>(logger_name, sink);
225
+ logger = std::make_shared<spdlog::logger>(logger_name, sink);
222
226
  } else {
223
227
  // Create the default thread pool for async logging
224
228
  spdlog::init_thread_pool(buffersz, 1);
@@ -226,23 +230,71 @@ create_file_logger(const configuration& logger_settings)
226
230
  // Get the thread pool so that we can actually construct the
227
231
  // object with already created sinks...
228
232
  auto tp = spdlog::thread_pool();
229
- file_logger = std::make_shared<spdlog::async_logger>(logger_name, sink, tp, spdlog::async_overflow_policy::block);
233
+ logger = std::make_shared<spdlog::async_logger>(logger_name, sink, tp, spdlog::async_overflow_policy::block);
230
234
  }
231
235
 
232
- file_logger->set_pattern(log_pattern);
233
- file_logger->set_level(translate_level(logger_settings.log_level));
236
+ logger->set_pattern(log_pattern);
237
+ logger->set_level(translate_level(logger_settings.log_level));
234
238
 
235
239
  // Set the flushing interval policy
236
240
  spdlog::flush_every(std::chrono::seconds(1));
237
241
 
238
- spdlog::register_logger(file_logger);
242
+ spdlog::register_logger(logger);
239
243
  } catch (const spdlog::spdlog_ex& ex) {
240
244
  std::string msg = std::string{ "Log initialization failed: " } + ex.what();
241
- return std::optional<std::string>{ msg };
245
+ return { msg, {} };
246
+ }
247
+ return { {}, logger };
248
+ }
249
+
250
+ /**
251
+ * Initialises the loggers. Called if the logger configuration is
252
+ * specified in a separate settings object.
253
+ */
254
+ std::optional<std::string>
255
+ create_file_logger(const configuration& logger_settings)
256
+ {
257
+ auto [error, logger] = create_file_logger_impl(file_logger_name, logger_settings);
258
+ if (error) {
259
+ return error;
260
+ }
261
+ file_logger = std::move(logger);
262
+ return {};
263
+ }
264
+
265
+ std::optional<std::string>
266
+ create_protocol_logger(const configuration& logger_settings)
267
+ {
268
+ if (logger_settings.filename.empty()) {
269
+ return "File name is missing";
270
+ }
271
+ auto config = logger_settings;
272
+ config.log_level = couchbase::core::logger::level::trace;
273
+ auto [error, logger] = create_file_logger_impl(protocol_logger_name, config);
274
+ if (error) {
275
+ return error;
242
276
  }
277
+ protocol_logger = std::move(logger);
243
278
  return {};
244
279
  }
245
280
 
281
+ bool
282
+ should_log_protocol()
283
+ {
284
+ return protocol_logger != nullptr;
285
+ }
286
+
287
+ namespace detail
288
+ {
289
+ void
290
+ log_protocol(const char* file, int line, const char* function, std::string_view msg)
291
+ {
292
+ if (should_log_protocol()) {
293
+ return protocol_logger->log(spdlog::source_loc{ file, line, function }, spdlog::level::level_enum::trace, msg);
294
+ }
295
+ }
296
+ } // namespace detail
297
+
246
298
  spdlog::logger*
247
299
  get()
248
300
  {
@@ -252,17 +304,20 @@ get()
252
304
  void
253
305
  reset()
254
306
  {
255
- spdlog::drop(logger_name);
307
+ spdlog::drop(file_logger_name);
256
308
  file_logger.reset();
309
+
310
+ spdlog::drop(protocol_logger_name);
311
+ protocol_logger.reset();
257
312
  }
258
313
 
259
314
  void
260
315
  create_blackhole_logger()
261
316
  {
262
317
  // delete if already exists
263
- spdlog::drop(logger_name);
318
+ spdlog::drop(file_logger_name);
264
319
 
265
- file_logger = std::make_shared<spdlog::logger>(logger_name, std::make_shared<spdlog::sinks::null_sink_mt>());
320
+ file_logger = std::make_shared<spdlog::logger>(file_logger_name, std::make_shared<spdlog::sinks::null_sink_mt>());
266
321
 
267
322
  file_logger->set_level(spdlog::level::off);
268
323
  file_logger->set_pattern(log_pattern);
@@ -274,11 +329,11 @@ void
274
329
  create_console_logger()
275
330
  {
276
331
  // delete if already exists
277
- spdlog::drop(logger_name);
332
+ spdlog::drop(file_logger_name);
278
333
 
279
334
  auto stderrsink = std::make_shared<spdlog::sinks::stderr_color_sink_mt>();
280
335
 
281
- file_logger = std::make_shared<spdlog::logger>(logger_name, stderrsink);
336
+ file_logger = std::make_shared<spdlog::logger>(file_logger_name, stderrsink);
282
337
  file_logger->set_level(spdlog::level::info);
283
338
  file_logger->set_pattern(log_pattern);
284
339
 
@@ -322,8 +377,13 @@ void
322
377
  set_log_levels(level lvl)
323
378
  {
324
379
  auto level = translate_level(lvl);
325
- // Apply the function to each registered spdlog::logger
380
+ // Apply the function to each registered spdlog::logger except protocol logger
326
381
  spdlog::apply_all([level](std::shared_ptr<spdlog::logger> l) {
382
+ if (l->name() == protocol_logger_name) {
383
+ l->set_level(spdlog::level::trace);
384
+ return;
385
+ }
386
+
327
387
  try {
328
388
  l->set_level(level);
329
389
  } catch (const spdlog::spdlog_ex& e) {
@@ -54,6 +54,17 @@ level_from_str(const std::string& str);
54
54
  std::optional<std::string>
55
55
  create_file_logger(const configuration& logger_settings);
56
56
 
57
+ /**
58
+ * Protocol logger writes only communication logs with the nodes.
59
+ *
60
+ * It accepts the same settings as a file logger, and writes only to the filesystem.
61
+ *
62
+ * @param logger_settings
63
+ * @return
64
+ */
65
+ std::optional<std::string>
66
+ create_protocol_logger(const configuration& logger_settings);
67
+
57
68
  /**
58
69
  * Initialize the logger with the blackhole logger object
59
70
  *
@@ -144,6 +155,9 @@ set_log_levels(level lvl);
144
155
  bool
145
156
  should_log(level lvl);
146
157
 
158
+ bool
159
+ should_log_protocol();
160
+
147
161
  namespace detail
148
162
  {
149
163
  /**
@@ -153,6 +167,9 @@ namespace detail
153
167
  */
154
168
  void
155
169
  log(const char* file, int line, const char* function, level lvl, std::string_view msg);
170
+
171
+ void
172
+ log_protocol(const char* file, int line, const char* function, std::string_view msg);
156
173
  } // namespace detail
157
174
 
158
175
  /**
@@ -168,6 +185,13 @@ log(const char* file, int line, const char* function, level lvl, const String& m
168
185
  detail::log(file, line, function, lvl, fmt::format(msg, std::forward<Args>(args)...));
169
186
  }
170
187
 
188
+ template<typename String, typename... Args>
189
+ inline void
190
+ log_protocol(const char* file, int line, const char* function, const String& msg, Args&&... args)
191
+ {
192
+ detail::log_protocol(file, line, function, fmt::format(msg, std::forward<Args>(args)...));
193
+ }
194
+
171
195
  /**
172
196
  * Tell the logger to flush its buffers
173
197
  */
@@ -214,6 +238,13 @@ is_initialized();
214
238
  #define CB_LOG_CRITICAL(...) \
215
239
  COUCHBASE_LOG(__FILE__, __LINE__, COUCHBASE_LOGGER_FUNCTION, couchbase::core::logger::level::critical, __VA_ARGS__)
216
240
 
241
+ #define CB_LOG_PROTOCOL(...) \
242
+ do { \
243
+ if (couchbase::core::logger::should_log_protocol()) { \
244
+ couchbase::core::logger::log_protocol(__FILE__, __LINE__, COUCHBASE_LOGGER_FUNCTION, __VA_ARGS__); \
245
+ } \
246
+ } while (false)
247
+
217
248
  /**
218
249
  * Convenience macros which log with the given level, and message, if the given
219
250
  * level is currently enabled.
@@ -29,3 +29,28 @@
29
29
  * couchbase::core::meta::sdk_version() function is available
30
30
  */
31
31
  #define COUCHBASE_CXX_CLIENT_HAS_SDK_SEMVER 1
32
+
33
+ /**
34
+ * couchbase::core::cluster_options and couchbase::security_options support
35
+ * passing TLS trust certificate by value
36
+ */
37
+ #define COUCHBASE_CXX_CLIENT_CAN_PASS_TLS_TRUST_CERTIFICATE_BY_VALUE 1
38
+
39
+ /**
40
+ * Range scan is available in the core
41
+ * couchbase::core::range_scan_orchestrator and relevant options in the core API
42
+ */
43
+ #define COUCHBASE_CXX_CLIENT_CORE_HAS_RANGE_SCAN 1
44
+
45
+ /**
46
+ * Query with reads from replica is available:
47
+ * - use_replica field in couchbase::core::operations::query_request
48
+ * - couchbase::query_options::use_replica()
49
+ */
50
+ #define COUCHBASE_CXX_CLIENT_QUERY_READ_FROM_REPLICA 1
51
+
52
+ /**
53
+ * Subdoc read from replica is available in the core
54
+ * couchbase::core::lookup_in_replica support
55
+ */
56
+ #define COUCHBASE_CXX_CLIENT_CORE_HAS_SUBDOC_READ_REPLICA 1