couchbase 3.0.0.alpha.5-universal-darwin-19 → 3.0.0.beta.1-universal-darwin-19
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.
- checksums.yaml +4 -4
- data/Gemfile +12 -3
- data/README.md +4 -2
- data/Rakefile +1 -1
- data/couchbase.gemspec +17 -12
- data/ext/.idea/misc.xml +12 -0
- data/ext/CMakeLists.txt +10 -1
- data/ext/build_config.hxx.in +20 -0
- data/ext/build_version.hxx.in +1 -1
- data/ext/couchbase/bucket.hxx +90 -24
- data/ext/couchbase/cluster.hxx +125 -84
- data/ext/couchbase/cluster_options.hxx +53 -0
- data/ext/couchbase/configuration.hxx +220 -2
- data/ext/couchbase/couchbase.cxx +134 -127
- data/ext/couchbase/io/dns_client.hxx +3 -1
- data/ext/couchbase/io/http_command.hxx +91 -0
- data/ext/couchbase/io/http_session.hxx +58 -19
- data/ext/couchbase/io/http_session_manager.hxx +26 -31
- data/ext/couchbase/io/mcbp_command.hxx +180 -0
- data/ext/couchbase/io/mcbp_message.hxx +5 -0
- data/ext/couchbase/io/mcbp_session.hxx +213 -98
- data/ext/couchbase/io/streams.hxx +165 -0
- data/ext/couchbase/operations.hxx +1 -1
- data/ext/couchbase/operations/analytics_dataset_create.hxx +1 -1
- data/ext/couchbase/operations/bucket_create.hxx +4 -2
- data/ext/couchbase/operations/bucket_drop.hxx +4 -2
- data/ext/couchbase/operations/bucket_flush.hxx +4 -2
- data/ext/couchbase/operations/bucket_get.hxx +4 -2
- data/ext/couchbase/operations/bucket_get_all.hxx +4 -2
- data/ext/couchbase/operations/bucket_update.hxx +4 -2
- data/ext/couchbase/operations/cluster_developer_preview_enable.hxx +4 -2
- data/ext/couchbase/operations/collection_create.hxx +4 -2
- data/ext/couchbase/operations/collection_drop.hxx +4 -2
- data/ext/couchbase/operations/document_analytics.hxx +0 -4
- data/ext/couchbase/operations/document_decrement.hxx +6 -3
- data/ext/couchbase/operations/document_get.hxx +3 -0
- data/ext/couchbase/operations/document_get_and_lock.hxx +3 -0
- data/ext/couchbase/operations/document_get_and_touch.hxx +5 -2
- data/ext/couchbase/operations/document_get_projected.hxx +12 -9
- data/ext/couchbase/operations/document_increment.hxx +6 -3
- data/ext/couchbase/operations/document_insert.hxx +5 -2
- data/ext/couchbase/operations/document_lookup_in.hxx +3 -0
- data/ext/couchbase/operations/document_mutate_in.hxx +6 -3
- data/ext/couchbase/operations/document_remove.hxx +3 -0
- data/ext/couchbase/operations/document_replace.hxx +5 -2
- data/ext/couchbase/operations/document_search.hxx +6 -7
- data/ext/couchbase/operations/document_touch.hxx +5 -2
- data/ext/couchbase/operations/document_unlock.hxx +3 -0
- data/ext/couchbase/operations/document_upsert.hxx +5 -2
- data/ext/couchbase/operations/query_index_build_deferred.hxx +3 -3
- data/ext/couchbase/operations/query_index_create.hxx +3 -3
- data/ext/couchbase/operations/query_index_drop.hxx +3 -3
- data/ext/couchbase/operations/query_index_get_all.hxx +3 -3
- data/ext/couchbase/operations/scope_create.hxx +4 -2
- data/ext/couchbase/operations/scope_drop.hxx +4 -2
- data/ext/couchbase/operations/scope_get_all.hxx +4 -2
- data/ext/couchbase/operations/search_index_analyze_document.hxx +2 -2
- data/ext/couchbase/operations/search_index_control_ingest.hxx +2 -2
- data/ext/couchbase/operations/search_index_control_plan_freeze.hxx +2 -2
- data/ext/couchbase/operations/search_index_control_query.hxx +2 -2
- data/ext/couchbase/operations/search_index_drop.hxx +2 -2
- data/ext/couchbase/operations/search_index_get.hxx +2 -2
- data/ext/couchbase/operations/search_index_get_all.hxx +2 -2
- data/ext/couchbase/operations/search_index_get_documents_count.hxx +2 -2
- data/ext/couchbase/operations/search_index_upsert.hxx +2 -2
- data/ext/couchbase/origin.hxx +148 -0
- data/ext/couchbase/protocol/cmd_cluster_map_change_notification.hxx +1 -6
- data/ext/couchbase/protocol/cmd_decrement.hxx +5 -5
- data/ext/couchbase/protocol/cmd_get_and_touch.hxx +5 -5
- data/ext/couchbase/protocol/cmd_get_cluster_config.hxx +1 -6
- data/ext/couchbase/protocol/cmd_increment.hxx +5 -5
- data/ext/couchbase/protocol/cmd_info.hxx +0 -11
- data/ext/couchbase/protocol/cmd_insert.hxx +5 -5
- data/ext/couchbase/protocol/cmd_mutate_in.hxx +6 -6
- data/ext/couchbase/protocol/cmd_replace.hxx +5 -5
- data/ext/couchbase/protocol/cmd_touch.hxx +1 -1
- data/ext/couchbase/protocol/cmd_upsert.hxx +5 -5
- data/ext/couchbase/timeout_defaults.hxx +7 -0
- data/ext/couchbase/utils/connection_string.hxx +139 -0
- data/ext/extconf.rb +44 -11
- data/ext/test/main.cxx +93 -15
- data/ext/third_party/http_parser/Makefile +160 -0
- data/ext/third_party/json/Makefile +77 -0
- data/lib/couchbase/analytics_options.rb +18 -4
- data/lib/couchbase/binary_collection.rb +2 -2
- data/lib/couchbase/binary_collection_options.rb +2 -2
- data/lib/couchbase/bucket.rb +4 -4
- data/lib/couchbase/cluster.rb +60 -46
- data/lib/couchbase/collection.rb +13 -13
- data/lib/couchbase/collection_options.rb +15 -9
- data/{bin/console → lib/couchbase/datastructures.rb} +4 -7
- data/lib/couchbase/datastructures/couchbase_list.rb +171 -0
- data/lib/couchbase/datastructures/couchbase_map.rb +205 -0
- data/lib/couchbase/datastructures/couchbase_queue.rb +145 -0
- data/lib/couchbase/datastructures/couchbase_set.rb +138 -0
- data/lib/couchbase/errors.rb +66 -63
- data/lib/couchbase/libcouchbase.bundle +0 -0
- data/lib/couchbase/management/user_manager.rb +1 -1
- data/lib/couchbase/mutation_state.rb +1 -0
- data/lib/couchbase/query_options.rb +25 -2
- data/lib/couchbase/scope.rb +0 -7
- data/lib/couchbase/search_options.rb +7 -0
- data/lib/couchbase/version.rb +1 -1
- data/lib/couchbase/view_options.rb +4 -3
- metadata +20 -82
- data/.github/workflows/tests-6.0.3.yml +0 -52
- data/.github/workflows/tests-dev-preview.yml +0 -55
- data/.github/workflows/tests.yml +0 -50
- data/.gitignore +0 -20
- data/.gitmodules +0 -21
- data/.idea/.gitignore +0 -5
- data/.idea/dictionaries/gem_terms.xml +0 -18
- data/.idea/inspectionProfiles/Project_Default.xml +0 -8
- data/.idea/vcs.xml +0 -13
- data/bin/check-cluster +0 -31
- data/bin/fetch-stats +0 -19
- data/bin/init-cluster +0 -82
- data/bin/jenkins/build-extension +0 -35
- data/bin/jenkins/install-dependencies +0 -47
- data/bin/jenkins/test-with-cbdyncluster +0 -58
- data/bin/setup +0 -24
- data/ext/couchbase/configuration_monitor.hxx +0 -93
- data/ext/couchbase/operations/command.hxx +0 -163
- data/rbi/couchbase.rbi +0 -79
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 0662d4e64ea7bc1e7b6cc7975cb9029a03ab89d70f279a1eef8d84cb9804510c
|
4
|
+
data.tar.gz: 80317092f682ecca19c7fc0410b1b1f7d44207a8efab95c4cf166140916dd9cc
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 641149befde0a43934f1afddaf10128b689bbc3b9f826d9da69bca82bed1b654eb9f667fc34e0c0cb9ace5d1d80eff6992f9c1b25f78e3811bfc1a909b48ba7b
|
7
|
+
data.tar.gz: 65f86e6f65023c3ac3e6d1f84373775f13cb2c03c67980f43c2b86ad54300e11f3ee04865068e5c8e727bfa3d44cf195fbdffd5477211740c7bd7583ceda784d
|
data/Gemfile
CHANGED
@@ -17,8 +17,17 @@ git_source(:github) { |repo_name| "https://github.com/#{repo_name}" }
|
|
17
17
|
|
18
18
|
gemspec
|
19
19
|
|
20
|
+
gem "rake"
|
21
|
+
|
20
22
|
group :development do
|
21
|
-
gem "
|
22
|
-
|
23
|
-
|
23
|
+
gem "yard"
|
24
|
+
platforms :mri do
|
25
|
+
gem "byebug"
|
26
|
+
end
|
27
|
+
end
|
28
|
+
|
29
|
+
group :test do
|
30
|
+
gem "minitest"
|
31
|
+
gem "minitest-reporters"
|
32
|
+
gem "simplecov-cobertura"
|
24
33
|
end
|
data/README.md
CHANGED
@@ -4,7 +4,7 @@ This repository contains the third generation of the official Couchbase SDK for
|
|
4
4
|
|
5
5
|
## Support and Feedback
|
6
6
|
|
7
|
-
If you find an issue, please file it in [our JIRA issue tracker](
|
7
|
+
If you find an issue, please file it in [our JIRA issue tracker](https://couchbase.com/issues/browse/RCBC).
|
8
8
|
Also you are always welcome on [our forum](https://forums.couchbase.com/c/ruby-sdk).
|
9
9
|
|
10
10
|
Please attach version information to ticket/post. To obtain this information use the following command:
|
@@ -13,10 +13,12 @@ Please attach version information to ticket/post. To obtain this information use
|
|
13
13
|
|
14
14
|
## Installation
|
15
15
|
|
16
|
+
The library tested with the MRI 2.5, 2.6 and 2.7. Supported platforms are Linux and MacOS.
|
17
|
+
|
16
18
|
Add this line to your application's Gemfile:
|
17
19
|
|
18
20
|
```ruby
|
19
|
-
gem "couchbase", "3.0.0.
|
21
|
+
gem "couchbase", "3.0.0.beta.1"
|
20
22
|
```
|
21
23
|
|
22
24
|
And then execute:
|
data/Rakefile
CHANGED
@@ -33,7 +33,7 @@ task :doc do
|
|
33
33
|
input_dir = File.join(__dir__, "lib")
|
34
34
|
output_dir = File.join(__dir__, "doc", "couchbase-ruby-client-#{Couchbase::VERSION[:sdk]}")
|
35
35
|
rm_rf output_dir
|
36
|
-
sh "yard doc --output-dir #{output_dir} #{input_dir}
|
36
|
+
sh "yard doc --hide-api private --output-dir #{output_dir} #{input_dir} --main README.md"
|
37
37
|
puts "#{File.realpath(output_dir)}/index.html"
|
38
38
|
end
|
39
39
|
|
data/couchbase.gemspec
CHANGED
@@ -26,13 +26,23 @@ Gem::Specification.new do |spec|
|
|
26
26
|
spec.homepage = "https://www.couchbase.com"
|
27
27
|
spec.license = "Apache-2.0"
|
28
28
|
|
29
|
-
spec.metadata
|
30
|
-
|
31
|
-
|
32
|
-
|
29
|
+
spec.metadata = {
|
30
|
+
"homepage_uri" => "https://docs.couchbase.com/ruby-sdk/3.0/hello-world/start-using-sdk.html",
|
31
|
+
"bug_tracker_uri" => "https://couchbase.com/issues/browse/RCBC",
|
32
|
+
"mailing_list_uri" => "https://forums.couchbase.com/c/ruby-sdk",
|
33
|
+
"source_code_uri" => "https://github.com/couchbasse/couchbase-ruby-client/tree/#{spec.version}",
|
34
|
+
"changelog_uri" => "https://github.com/couchbase/couchbase-ruby-client/releases/tag/#{spec.version}",
|
35
|
+
"documentation_uri" => "https://docs.couchbase.com/sdk-api/couchbase-ruby-client-#{spec.version}/index.html",
|
36
|
+
"github_repo" => "ssh://github.com/couchbase/couchbase-ruby-client",
|
37
|
+
}
|
33
38
|
|
34
39
|
spec.files = Dir.chdir(File.expand_path("..", __FILE__)) do
|
35
40
|
exclude_paths = %w[
|
41
|
+
.idea
|
42
|
+
.github
|
43
|
+
.gitignore
|
44
|
+
.gitmodules
|
45
|
+
bin
|
36
46
|
test
|
37
47
|
spec
|
38
48
|
features
|
@@ -57,17 +67,12 @@ Gem::Specification.new do |spec|
|
|
57
67
|
ext/third_party/spdlog/tests
|
58
68
|
]
|
59
69
|
`git ls-files --recurse-submodules -z`
|
60
|
-
|
61
|
-
|
70
|
+
.split("\x0")
|
71
|
+
.reject { |f| f.match(%r{^(#{Regexp.union(exclude_paths)})}) }
|
62
72
|
end
|
63
73
|
spec.bindir = "exe"
|
64
74
|
spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
|
65
75
|
spec.require_paths = ["lib"]
|
66
76
|
spec.extensions = ["ext/extconf.rb"]
|
67
|
-
spec.rdoc_options
|
68
|
-
|
69
|
-
spec.add_development_dependency "bundler", "~> 2.1"
|
70
|
-
spec.add_development_dependency "rake", "~> 13.0"
|
71
|
-
spec.add_development_dependency "minitest", "~> 5.14"
|
72
|
-
spec.add_development_dependency "minitest-reporters", "~> 1.4"
|
77
|
+
spec.rdoc_options << "--exclude" << "ext/"
|
73
78
|
end
|
data/ext/.idea/misc.xml
CHANGED
@@ -1,4 +1,16 @@
|
|
1
1
|
<?xml version="1.0" encoding="UTF-8"?>
|
2
2
|
<project version="4">
|
3
3
|
<component name="CMakeWorkspace" PROJECT_DIR="$PROJECT_DIR$" />
|
4
|
+
<component name="CidrRootsConfiguration">
|
5
|
+
<sourceRoots>
|
6
|
+
<file path="$PROJECT_DIR$/couchbase" />
|
7
|
+
</sourceRoots>
|
8
|
+
<libraryRoots>
|
9
|
+
<file path="$PROJECT_DIR$/third_party" />
|
10
|
+
</libraryRoots>
|
11
|
+
<excludeRoots>
|
12
|
+
<file path="$PROJECT_DIR$/cmake-build-debug" />
|
13
|
+
<file path="$PROJECT_DIR$/cmake-build-debug-system-gcc" />
|
14
|
+
</excludeRoots>
|
15
|
+
</component>
|
4
16
|
</project>
|
data/ext/CMakeLists.txt
CHANGED
@@ -29,7 +29,7 @@ if(MSVC)
|
|
29
29
|
target_compile_options(project_warnings INTERFACE /W4 /WX "/permissive-")
|
30
30
|
else()
|
31
31
|
option(ONLY_COVERAGE "Build only tests necessary for coverage" FALSE)
|
32
|
-
option(
|
32
|
+
option(STATIC_STDLIB "Statically link C++ standard library" FALSE)
|
33
33
|
option(ENABLE_COVERAGE "Enable coverage reporting for gcc/clang" FALSE)
|
34
34
|
option(ENABLE_FUZZERS "Enable fuzz testing tools" FALSE)
|
35
35
|
|
@@ -52,6 +52,11 @@ else()
|
|
52
52
|
target_link_libraries(project_options INTERFACE -fsanitize=thread)
|
53
53
|
endif()
|
54
54
|
|
55
|
+
if(STATIC_STDLIB)
|
56
|
+
target_compile_options(project_options INTERFACE -static-libgcc -static-libstdc++)
|
57
|
+
target_link_options(project_options INTERFACE -static-libgcc -static-libstdc++)
|
58
|
+
endif()
|
59
|
+
|
55
60
|
target_compile_options(
|
56
61
|
project_warnings
|
57
62
|
INTERFACE -Wall
|
@@ -87,6 +92,9 @@ else()
|
|
87
92
|
endif()
|
88
93
|
endif()
|
89
94
|
|
95
|
+
# Read more at https://wiki.wireshark.org/TLS
|
96
|
+
option(TLS_KEY_LOG_FILE "Path to file to write per-session secrets (Useful for Wireshark SSL/TLS dissection)")
|
97
|
+
|
90
98
|
include(FindOpenSSL)
|
91
99
|
message(STATUS "OPENSSL_VERSION: ${OPENSSL_VERSION}")
|
92
100
|
message(STATUS "OPENSSL_INCLUDEDIRS: ${OPENSSL_INCLUDE_DIR}")
|
@@ -129,6 +137,7 @@ endif()
|
|
129
137
|
|
130
138
|
string(TIMESTAMP BACKEND_BUILD_TIMESTAMP "%Y-%m-%d %H:%M:%S" UTC)
|
131
139
|
configure_file(${PROJECT_SOURCE_DIR}/build_version.hxx.in ${PROJECT_BINARY_DIR}/generated/build_version.hxx @ONLY)
|
140
|
+
configure_file(${PROJECT_SOURCE_DIR}/build_config.hxx.in ${PROJECT_BINARY_DIR}/generated/build_config.hxx @ONLY)
|
132
141
|
add_library(couchbase SHARED couchbase/couchbase.cxx)
|
133
142
|
target_include_directories(couchbase PRIVATE ${PROJECT_BINARY_DIR}/generated)
|
134
143
|
target_link_libraries(
|
@@ -0,0 +1,20 @@
|
|
1
|
+
/* -*- Mode: C++; tab-width: 4; c-basic-offset: 4; indent-tabs-mode: nil -*- */
|
2
|
+
/*
|
3
|
+
* Copyright 2020 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
|
+
#pragma once
|
19
|
+
|
20
|
+
#cmakedefine TLS_KEY_LOG_FILE "@TLS_KEY_LOG_FILE@"
|
data/ext/build_version.hxx.in
CHANGED
@@ -22,5 +22,5 @@
|
|
22
22
|
#define BACKEND_C_COMPILER "@CMAKE_C_COMPILER_ID@ @CMAKE_C_COMPILER_VERSION@"
|
23
23
|
#define BACKEND_SYSTEM "@CMAKE_SYSTEM@"
|
24
24
|
#define BACKEND_SYSTEM_PROCESSOR "@CMAKE_SYSTEM_PROCESSOR@"
|
25
|
-
#define BACKEND_GIT_REVISION "
|
25
|
+
#define BACKEND_GIT_REVISION "f01d0c237750cc67ee75325ed160bc0da1d2bf7a"
|
26
26
|
|
data/ext/couchbase/bucket.hxx
CHANGED
@@ -18,19 +18,29 @@
|
|
18
18
|
#pragma once
|
19
19
|
|
20
20
|
#include <utility>
|
21
|
+
#include <queue>
|
21
22
|
|
22
|
-
#include <configuration_monitor.hxx>
|
23
23
|
#include <operations.hxx>
|
24
|
+
#include <origin.hxx>
|
24
25
|
|
25
26
|
namespace couchbase
|
26
27
|
{
|
27
|
-
class bucket
|
28
|
+
class bucket : public std::enable_shared_from_this<bucket>
|
28
29
|
{
|
29
30
|
public:
|
30
|
-
explicit bucket(
|
31
|
-
|
31
|
+
explicit bucket(const std::string& client_id,
|
32
|
+
asio::io_context& ctx,
|
33
|
+
asio::ssl::context& tls,
|
34
|
+
std::string name,
|
35
|
+
couchbase::origin origin,
|
36
|
+
const std::vector<protocol::hello_feature>& known_features)
|
37
|
+
|
38
|
+
: client_id_(client_id)
|
39
|
+
, ctx_(ctx)
|
40
|
+
, tls_(tls)
|
32
41
|
, name_(std::move(name))
|
33
|
-
,
|
42
|
+
, origin_(std::move(origin))
|
43
|
+
, known_features_(known_features)
|
34
44
|
{
|
35
45
|
}
|
36
46
|
|
@@ -44,21 +54,55 @@ class bucket
|
|
44
54
|
return name_;
|
45
55
|
}
|
46
56
|
|
47
|
-
|
57
|
+
template<typename Handler>
|
58
|
+
void bootstrap(Handler&& handler)
|
48
59
|
{
|
49
|
-
|
50
|
-
|
60
|
+
std::shared_ptr<io::mcbp_session> new_session;
|
61
|
+
if (origin_.options().enable_tls) {
|
62
|
+
new_session = std::make_shared<io::mcbp_session>(client_id_, ctx_, tls_, origin_, name_, known_features_);
|
63
|
+
} else {
|
64
|
+
new_session = std::make_shared<io::mcbp_session>(client_id_, ctx_, origin_, name_, known_features_);
|
51
65
|
}
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
|
66
|
+
new_session->bootstrap([self = shared_from_this(), new_session, h = std::forward<Handler>(handler)](
|
67
|
+
std::error_code ec, const configuration& cfg) mutable {
|
68
|
+
if (!ec) {
|
69
|
+
self->config_ = cfg;
|
70
|
+
size_t this_index = new_session->index();
|
71
|
+
self->sessions_.emplace(this_index, std::move(new_session));
|
72
|
+
if (cfg.nodes.size() > 1) {
|
73
|
+
for (const auto& n : cfg.nodes) {
|
74
|
+
if (n.index != this_index) {
|
75
|
+
couchbase::origin origin(
|
76
|
+
self->origin_.get_username(),
|
77
|
+
self->origin_.get_password(),
|
78
|
+
n.hostname_for(self->origin_.options().network),
|
79
|
+
n.port_or(self->origin_.options().network, service_type::kv, self->origin_.options().enable_tls, 0),
|
80
|
+
self->origin_.options());
|
81
|
+
std::shared_ptr<io::mcbp_session> s;
|
82
|
+
if (self->origin_.options().enable_tls) {
|
83
|
+
s = std::make_shared<io::mcbp_session>(
|
84
|
+
self->client_id_, self->ctx_, self->tls_, origin, self->name_, self->known_features_);
|
85
|
+
} else {
|
86
|
+
s = std::make_shared<io::mcbp_session>(
|
87
|
+
self->client_id_, self->ctx_, origin, self->name_, self->known_features_);
|
88
|
+
}
|
89
|
+
s->bootstrap([host = n.hostname, bucket = self->name_](std::error_code err, const configuration& /*config*/) {
|
90
|
+
// TODO: retry, we know that auth is correct
|
91
|
+
if (err) {
|
92
|
+
spdlog::warn("unable to bootstrap node {} ({}): {}", host, bucket, err.message());
|
93
|
+
}
|
94
|
+
});
|
95
|
+
self->sessions_.emplace(n.index, std::move(s));
|
96
|
+
}
|
97
|
+
}
|
98
|
+
}
|
99
|
+
while (!self->deferred_commands_.empty()) {
|
100
|
+
self->deferred_commands_.front()();
|
101
|
+
self->deferred_commands_.pop();
|
102
|
+
}
|
103
|
+
}
|
104
|
+
h(ec, cfg);
|
105
|
+
});
|
62
106
|
}
|
63
107
|
|
64
108
|
template<typename Request, typename Handler>
|
@@ -67,11 +111,16 @@ class bucket
|
|
67
111
|
if (closed_) {
|
68
112
|
return;
|
69
113
|
}
|
70
|
-
|
71
|
-
std::
|
72
|
-
|
73
|
-
|
74
|
-
|
114
|
+
auto cmd = std::make_shared<operations::mcbp_command<Request>>(ctx_, request);
|
115
|
+
cmd->start([cmd, handler = std::forward<Handler>(handler)](std::error_code ec, std::optional<io::mcbp_message> msg) mutable {
|
116
|
+
using encoded_response_type = typename Request::encoded_response_type;
|
117
|
+
handler(make_response(ec, cmd->request, msg ? encoded_response_type(*msg) : encoded_response_type{}));
|
118
|
+
});
|
119
|
+
if (config_) {
|
120
|
+
map_and_send(cmd);
|
121
|
+
} else {
|
122
|
+
deferred_commands_.emplace([self = shared_from_this(), cmd]() { self->map_and_send(cmd); });
|
123
|
+
}
|
75
124
|
}
|
76
125
|
|
77
126
|
void close()
|
@@ -85,10 +134,27 @@ class bucket
|
|
85
134
|
}
|
86
135
|
}
|
87
136
|
|
137
|
+
template<typename Request>
|
138
|
+
void map_and_send(std::shared_ptr<operations::mcbp_command<Request>> cmd)
|
139
|
+
{
|
140
|
+
size_t index = 0;
|
141
|
+
std::tie(cmd->request.partition, index) = config_->map_key(cmd->request.id.key);
|
142
|
+
auto session = sessions_.at(index);
|
143
|
+
cmd->send_to(session);
|
144
|
+
}
|
145
|
+
|
88
146
|
private:
|
147
|
+
std::string client_id_;
|
89
148
|
asio::io_context& ctx_;
|
149
|
+
asio::ssl::context& tls_;
|
90
150
|
std::string name_;
|
91
|
-
|
151
|
+
origin origin_;
|
152
|
+
|
153
|
+
std::optional<configuration> config_{};
|
154
|
+
std::vector<protocol::hello_feature> known_features_;
|
155
|
+
|
156
|
+
std::queue<std::function<void()>> deferred_commands_{};
|
157
|
+
|
92
158
|
bool closed_{ false };
|
93
159
|
std::map<size_t, std::shared_ptr<io::mcbp_session>> sessions_{};
|
94
160
|
};
|
data/ext/couchbase/cluster.hxx
CHANGED
@@ -19,36 +19,21 @@
|
|
19
19
|
|
20
20
|
#include <utility>
|
21
21
|
#include <thread>
|
22
|
+
#include <fstream>
|
23
|
+
|
24
|
+
#include <asio/ssl.hpp>
|
22
25
|
|
23
26
|
#include <io/mcbp_session.hxx>
|
24
27
|
#include <io/http_session_manager.hxx>
|
28
|
+
#include <io/http_command.hxx>
|
29
|
+
#include <io/dns_client.hxx>
|
30
|
+
#include <origin.hxx>
|
25
31
|
#include <bucket.hxx>
|
26
32
|
#include <operations.hxx>
|
27
33
|
#include <operations/document_query.hxx>
|
28
34
|
|
29
35
|
namespace couchbase
|
30
36
|
{
|
31
|
-
struct origin {
|
32
|
-
std::string username;
|
33
|
-
std::string password;
|
34
|
-
std::string hostname;
|
35
|
-
|
36
|
-
[[nodiscard]] const std::string& get_username() const
|
37
|
-
{
|
38
|
-
return username;
|
39
|
-
}
|
40
|
-
|
41
|
-
[[nodiscard]] const std::string& get_password() const
|
42
|
-
{
|
43
|
-
return password;
|
44
|
-
}
|
45
|
-
|
46
|
-
[[nodiscard]] std::pair<std::string, std::string> get_address() const
|
47
|
-
{
|
48
|
-
return { hostname, "11210" };
|
49
|
-
}
|
50
|
-
};
|
51
|
-
|
52
37
|
class cluster
|
53
38
|
{
|
54
39
|
public:
|
@@ -56,88 +41,53 @@ class cluster
|
|
56
41
|
: id_(uuid::to_string(uuid::random()))
|
57
42
|
, ctx_(ctx)
|
58
43
|
, work_(asio::make_work_guard(ctx_))
|
59
|
-
,
|
60
|
-
, session_manager_(std::make_shared<io::http_session_manager>(id_, ctx_))
|
44
|
+
, tls_(asio::ssl::context::tls_client)
|
45
|
+
, session_manager_(std::make_shared<io::http_session_manager>(id_, ctx_, tls_))
|
46
|
+
, dns_config_(io::dns::dns_config::get())
|
47
|
+
, dns_client_(ctx_)
|
61
48
|
{
|
62
49
|
}
|
63
50
|
|
64
|
-
~cluster()
|
65
|
-
{
|
66
|
-
work_.reset();
|
67
|
-
}
|
68
|
-
|
69
51
|
template<typename Handler>
|
70
52
|
void open(const couchbase::origin& origin, Handler&& handler)
|
71
53
|
{
|
72
|
-
auto address = origin.get_address();
|
73
54
|
origin_ = origin;
|
74
|
-
|
75
|
-
|
76
|
-
|
77
|
-
|
78
|
-
[this, handler = std::forward<Handler>(handler)](std::error_code ec, configuration config) mutable {
|
79
|
-
session_manager_->set_configuration(config);
|
80
|
-
handler(ec);
|
81
|
-
});
|
55
|
+
if (origin_.options().enable_dns_srv) {
|
56
|
+
return do_dns_srv(std::forward<Handler>(handler));
|
57
|
+
}
|
58
|
+
do_open(std::forward<Handler>(handler));
|
82
59
|
}
|
83
60
|
|
84
61
|
template<typename Handler>
|
85
62
|
void close(Handler&& handler)
|
86
63
|
{
|
87
64
|
asio::post(asio::bind_executor(ctx_, [this, handler = std::forward<Handler>(handler)]() {
|
88
|
-
session_
|
65
|
+
if (session_) {
|
66
|
+
session_->stop();
|
67
|
+
}
|
89
68
|
for (auto& bucket : buckets_) {
|
90
69
|
bucket.second->close();
|
91
70
|
}
|
92
71
|
handler();
|
72
|
+
work_.reset();
|
93
73
|
}));
|
94
74
|
}
|
95
75
|
|
96
76
|
template<typename Handler>
|
97
77
|
void open_bucket(const std::string& bucket_name, Handler&& handler)
|
98
78
|
{
|
99
|
-
|
100
|
-
|
79
|
+
std::vector<protocol::hello_feature> known_features;
|
80
|
+
if (session_ && session_->has_config()) {
|
81
|
+
known_features = session_->supported_features();
|
101
82
|
}
|
102
|
-
|
103
|
-
|
104
|
-
|
105
|
-
|
106
|
-
|
107
|
-
|
108
|
-
|
109
|
-
|
110
|
-
[this, name = bucket_name, new_session, known_features, h = std::forward<Handler>(handler)](
|
111
|
-
std::error_code ec, configuration cfg) mutable {
|
112
|
-
if (!ec) {
|
113
|
-
if (!session_->supports_gcccp()) {
|
114
|
-
session_manager_->set_configuration(cfg);
|
115
|
-
}
|
116
|
-
auto b = std::make_shared<bucket>(ctx_, name, cfg);
|
117
|
-
size_t this_index = new_session->index();
|
118
|
-
b->set_node(this_index, new_session);
|
119
|
-
if (cfg.nodes.size() > 1) {
|
120
|
-
for (const auto& n : cfg.nodes) {
|
121
|
-
if (n.index != this_index) {
|
122
|
-
auto s = std::make_shared<io::mcbp_session>(id_, ctx_, name, known_features);
|
123
|
-
b->set_node(n.index, s);
|
124
|
-
s->bootstrap(n.hostname,
|
125
|
-
std::to_string(*n.services_plain.key_value),
|
126
|
-
origin_.get_username(),
|
127
|
-
origin_.get_password(),
|
128
|
-
[s, i = n.index, b](std::error_code err, configuration /*config*/) {
|
129
|
-
if (err) {
|
130
|
-
spdlog::warn("unable to bootstrap node: {}", err.message());
|
131
|
-
b->remove_node(i);
|
132
|
-
}
|
133
|
-
});
|
134
|
-
}
|
135
|
-
}
|
136
|
-
}
|
137
|
-
buckets_.emplace(name, std::move(b));
|
138
|
-
}
|
139
|
-
h(ec);
|
140
|
-
});
|
83
|
+
auto b = std::make_shared<bucket>(id_, ctx_, tls_, bucket_name, origin_, known_features);
|
84
|
+
b->bootstrap([this, handler = std::forward<Handler>(handler)](std::error_code ec, const configuration& config) mutable {
|
85
|
+
if (!ec && !session_->supports_gcccp()) {
|
86
|
+
session_manager_->set_configuration(config, origin_.options());
|
87
|
+
}
|
88
|
+
handler(ec);
|
89
|
+
});
|
90
|
+
buckets_.emplace(bucket_name, b);
|
141
91
|
}
|
142
92
|
|
143
93
|
template<class Request, class Handler>
|
@@ -153,11 +103,11 @@ class cluster
|
|
153
103
|
template<class Request, class Handler>
|
154
104
|
void execute_http(Request request, Handler&& handler)
|
155
105
|
{
|
156
|
-
auto session = session_manager_->check_out(Request::type, origin_.
|
106
|
+
auto session = session_manager_->check_out(Request::type, origin_.get_username(), origin_.get_password());
|
157
107
|
if (!session) {
|
158
108
|
return handler(operations::make_response(std::make_error_code(error::common_errc::service_not_available), request, {}));
|
159
109
|
}
|
160
|
-
auto cmd = std::make_shared<operations::
|
110
|
+
auto cmd = std::make_shared<operations::http_command<Request>>(ctx_, request);
|
161
111
|
cmd->send_to(session, [this, session, handler = std::forward<Handler>(handler)](typename Request::response_type resp) mutable {
|
162
112
|
handler(std::move(resp));
|
163
113
|
session_manager_->check_in(Request::type, session);
|
@@ -165,12 +115,103 @@ class cluster
|
|
165
115
|
}
|
166
116
|
|
167
117
|
private:
|
118
|
+
template<typename Handler>
|
119
|
+
void do_dns_srv(Handler&& handler)
|
120
|
+
{
|
121
|
+
std::string hostname;
|
122
|
+
std::string service;
|
123
|
+
std::tie(hostname, service) = origin_.next_address();
|
124
|
+
service = origin_.options().enable_tls ? "_couchbases" : "_couchbase";
|
125
|
+
dns_client_.query_srv(
|
126
|
+
hostname,
|
127
|
+
service,
|
128
|
+
[hostname, this, handler = std::forward<Handler>(handler)](couchbase::io::dns::dns_client::dns_srv_response resp) mutable {
|
129
|
+
if (resp.ec) {
|
130
|
+
spdlog::warn("failed to fetch DNS SRV records for \"{}\" ({}), assuming that cluster is listening this address",
|
131
|
+
hostname,
|
132
|
+
resp.ec.message());
|
133
|
+
} else if (resp.targets.empty()) {
|
134
|
+
spdlog::warn("DNS SRV query returned 0 records for \"{}\", assuming that cluster is listening this address", hostname);
|
135
|
+
} else {
|
136
|
+
origin::node_list nodes;
|
137
|
+
nodes.reserve(resp.targets.size());
|
138
|
+
for (const auto& address : resp.targets) {
|
139
|
+
origin::node_entry node;
|
140
|
+
node.first = address.hostname;
|
141
|
+
node.second = std::to_string(address.port);
|
142
|
+
nodes.emplace_back(node);
|
143
|
+
}
|
144
|
+
origin_.set_nodes(nodes);
|
145
|
+
spdlog::info("replace list of bootstrap nodes with addresses from DNS SRV of \"{}\": [{}]",
|
146
|
+
hostname,
|
147
|
+
fmt::join(origin_.get_nodes(), ", "));
|
148
|
+
}
|
149
|
+
return do_open(std::forward<Handler>(handler));
|
150
|
+
});
|
151
|
+
}
|
152
|
+
|
153
|
+
template<typename Handler>
|
154
|
+
void do_open(Handler&& handler)
|
155
|
+
{
|
156
|
+
if (origin_.options().enable_tls) {
|
157
|
+
tls_.set_options(asio::ssl::context::default_workarounds | asio::ssl::context::no_sslv2 | asio::ssl::context::no_sslv3);
|
158
|
+
if (!origin_.options().trust_certificate.empty()) {
|
159
|
+
std::error_code ec{};
|
160
|
+
tls_.use_certificate_chain_file(origin_.options().trust_certificate, ec);
|
161
|
+
if (ec) {
|
162
|
+
spdlog::error("unable to load certificate chain \"{}\": {}", origin_.options().trust_certificate, ec.message());
|
163
|
+
return handler(ec);
|
164
|
+
}
|
165
|
+
}
|
166
|
+
#ifdef TLS_KEY_LOG_FILE
|
167
|
+
SSL_CTX_set_keylog_callback(tls_.native_handle(), [](const SSL* /* ssl */, const char* line) {
|
168
|
+
std::ofstream keylog(TLS_KEY_LOG_FILE, std::ios::out | std::ios::app | std::ios::binary);
|
169
|
+
keylog << std::string_view(line) << std::endl;
|
170
|
+
});
|
171
|
+
spdlog::critical("TLS_KEY_LOG_FILE was set to \"{}\" during build, all TLS keys will be logged for network analysis "
|
172
|
+
"(https://wiki.wireshark.org/TLS). DO NOT USE THIS BUILD IN PRODUCTION",
|
173
|
+
TLS_KEY_LOG_FILE);
|
174
|
+
#endif
|
175
|
+
session_ = std::make_shared<io::mcbp_session>(id_, ctx_, tls_, origin_);
|
176
|
+
} else {
|
177
|
+
session_ = std::make_shared<io::mcbp_session>(id_, ctx_, origin_);
|
178
|
+
}
|
179
|
+
session_->bootstrap([this, handler = std::forward<Handler>(handler)](std::error_code ec, const configuration& config) mutable {
|
180
|
+
if (!ec) {
|
181
|
+
if (origin_.options().network == "auto") {
|
182
|
+
origin_.options().network = config.select_network(session_->bootstrap_hostname());
|
183
|
+
spdlog::info(R"({} detected network is "{}")", session_->log_prefix(), origin_.options().network);
|
184
|
+
}
|
185
|
+
if (origin_.options().network != "default") {
|
186
|
+
origin::node_list nodes;
|
187
|
+
nodes.reserve(config.nodes.size());
|
188
|
+
for (const auto& address : config.nodes) {
|
189
|
+
origin::node_entry node;
|
190
|
+
node.first = address.hostname_for(origin_.options().network);
|
191
|
+
node.second =
|
192
|
+
std::to_string(address.port_or(origin_.options().network, service_type::kv, origin_.options().enable_tls, 0));
|
193
|
+
nodes.emplace_back(node);
|
194
|
+
}
|
195
|
+
origin_.set_nodes(nodes);
|
196
|
+
spdlog::info("replace list of bootstrap nodes with addresses of alternative network \"{}\": [{}]",
|
197
|
+
origin_.options().network,
|
198
|
+
fmt::join(origin_.get_nodes(), ","));
|
199
|
+
}
|
200
|
+
session_manager_->set_configuration(config, origin_.options());
|
201
|
+
}
|
202
|
+
handler(ec);
|
203
|
+
});
|
204
|
+
}
|
205
|
+
|
168
206
|
std::string id_;
|
169
207
|
asio::io_context& ctx_;
|
170
208
|
asio::executor_work_guard<asio::io_context::executor_type> work_;
|
171
|
-
|
209
|
+
asio::ssl::context tls_;
|
172
210
|
std::shared_ptr<io::http_session_manager> session_manager_;
|
173
|
-
|
174
|
-
|
211
|
+
io::dns::dns_config& dns_config_;
|
212
|
+
couchbase::io::dns::dns_client dns_client_;
|
213
|
+
std::shared_ptr<io::mcbp_session> session_{};
|
214
|
+
std::map<std::string, std::shared_ptr<bucket>> buckets_{};
|
215
|
+
couchbase::origin origin_{};
|
175
216
|
};
|
176
217
|
} // namespace couchbase
|