couchbase 3.0.0.alpha.5 → 3.0.0.beta.1
Sign up to get free protection for your applications and to get access to all the features.
- 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/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: 1e71b3d69cab6a09f02460f5b983a908c256a76e12dd68f57fab9173c6a50d0e
|
4
|
+
data.tar.gz: b58766149d745a869828fe7f2f04f56182560de48a3365b95b253313f7f428c4
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 12b4ab101a664897933c2ca98841c1d7cd27c6b5a15653eb2b48e59eba69f76f431ce25b316eba392ad8f104cdcde0fa44b38004a341e316141d821a7256c852
|
7
|
+
data.tar.gz: 4a1723022980425bc7b0a907d5487ae72c654d29709f1137a32349a98eab7e11f23d75a95414df60a35097e9eae4cd9ec2414d184877b95c06f62cb97825770a
|
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
|