Skip to content

Commit ab763ed

Browse files
authored
v1::read_concern (CXX-3237, CXX-3238) (#1503)
1 parent 232838b commit ab763ed

File tree

15 files changed

+655
-165
lines changed

15 files changed

+655
-165
lines changed

src/mongocxx/include/mongocxx/v1/read_concern.hpp

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -190,6 +190,11 @@ class read_concern {
190190
}
191191
/// @}
192192
///
193+
194+
class internal;
195+
196+
private:
197+
/* explicit(false) */ read_concern(void* impl);
193198
};
194199

195200
} // namespace v1

src/mongocxx/include/mongocxx/v_noabi/mongocxx/read_concern-fwd.hpp

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,8 @@
1414

1515
#pragma once
1616

17+
#include <mongocxx/v1/read_concern-fwd.hpp>
18+
1719
#include <mongocxx/config/prelude.hpp>
1820

1921
namespace mongocxx {
@@ -26,7 +28,7 @@ class read_concern;
2628

2729
namespace mongocxx {
2830

29-
using ::mongocxx::v_noabi::read_concern;
31+
using v_noabi::read_concern;
3032

3133
} // namespace mongocxx
3234

@@ -36,3 +38,6 @@ using ::mongocxx::v_noabi::read_concern;
3638
/// @file
3739
/// Declares @ref mongocxx::v_noabi::read_concern.
3840
///
41+
/// @par Includes
42+
/// - @ref mongocxx/v1/read_concern-fwd.hpp
43+
///

src/mongocxx/include/mongocxx/v_noabi/mongocxx/read_concern.hpp

Lines changed: 71 additions & 41 deletions
Original file line numberDiff line numberDiff line change
@@ -14,20 +14,26 @@
1414

1515
#pragma once
1616

17-
#include <memory>
18-
19-
#include <mongocxx/client-fwd.hpp>
20-
#include <mongocxx/collection-fwd.hpp>
21-
#include <mongocxx/database-fwd.hpp>
22-
#include <mongocxx/options/transaction-fwd.hpp>
2317
#include <mongocxx/read_concern-fwd.hpp> // IWYU pragma: export
24-
#include <mongocxx/uri-fwd.hpp>
18+
19+
//
20+
21+
#include <mongocxx/v1/read_concern.hpp> // IWYU pragma: export
22+
23+
#include <memory> // IWYU pragma: keep: backward compatibility, to be removed.
24+
#include <utility>
25+
26+
#include <mongocxx/client-fwd.hpp> // IWYU pragma: keep: backward compatibility, to be removed.
27+
#include <mongocxx/collection-fwd.hpp> // IWYU pragma: keep: backward compatibility, to be removed.
28+
#include <mongocxx/database-fwd.hpp> // IWYU pragma: keep: backward compatibility, to be removed.
29+
#include <mongocxx/options/transaction-fwd.hpp> // IWYU pragma: keep: backward compatibility, to be removed.
30+
#include <mongocxx/uri-fwd.hpp> // IWYU pragma: keep: backward compatibility, to be removed.
2531

2632
#include <bsoncxx/document/value.hpp>
2733
#include <bsoncxx/stdx/optional.hpp> // IWYU pragma: keep: backward compatibility, to be removed.
2834
#include <bsoncxx/stdx/string_view.hpp>
2935

30-
#include <mongocxx/options/transaction.hpp>
36+
#include <mongocxx/options/transaction.hpp> // IWYU pragma: keep: backward compatibility, to be removed.
3137

3238
#include <mongocxx/config/prelude.hpp>
3339

@@ -46,6 +52,9 @@ namespace v_noabi {
4652
/// - [Read Concern (MongoDB Manual)](https://www.mongodb.com/docs/manual/reference/read-concern/)
4753
///
4854
class read_concern {
55+
private:
56+
v1::read_concern _rc;
57+
4958
public:
5059
///
5160
/// A class to represent the read concern level for read operations.
@@ -71,32 +80,31 @@ class read_concern {
7180
/// run with this read_concern will use the server's default read_concern instead of
7281
/// specifying one.
7382
///
74-
MONGOCXX_ABI_EXPORT_CDECL() read_concern();
75-
76-
///
77-
/// Copy constructs a read_concern.
78-
///
79-
MONGOCXX_ABI_EXPORT_CDECL() read_concern(read_concern const&);
83+
read_concern() = default;
8084

8185
///
82-
/// Copy assigns a read_concern.
86+
/// Construct with the @ref mongocxx::v1 equivalent.
8387
///
84-
MONGOCXX_ABI_EXPORT_CDECL(read_concern&) operator=(read_concern const&);
88+
/* explicit(false) */ read_concern(v1::read_concern rc) : _rc{std::move(rc)} {}
8589

8690
///
87-
/// Move constructs a read_concern.
91+
/// Convert to the @ref mongocxx::v1 equivalent.
8892
///
89-
MONGOCXX_ABI_EXPORT_CDECL() read_concern(read_concern&&) noexcept;
90-
93+
/// @par Postconditions:
94+
/// - `other` is in an assign-or-destroy-only state.
9195
///
92-
/// Move assigns a read_concern.
96+
/// @warning Invalidates all associated iterators and views.
9397
///
94-
MONGOCXX_ABI_EXPORT_CDECL(read_concern&) operator=(read_concern&&) noexcept;
98+
explicit operator v1::read_concern() && {
99+
return std::move(_rc);
100+
}
95101

96102
///
97-
/// Destroys a read_concern.
103+
/// Convert to the @ref mongocxx::v1 equivalent.
98104
///
99-
MONGOCXX_ABI_EXPORT_CDECL() ~read_concern();
105+
explicit operator v1::read_concern() const& {
106+
return _rc;
107+
}
100108

101109
///
102110
/// Sets the read concern level.
@@ -118,7 +126,9 @@ class read_concern {
118126
///
119127
/// @return The read concern level.
120128
///
121-
MONGOCXX_ABI_EXPORT_CDECL(level) acknowledge_level() const;
129+
level acknowledge_level() const {
130+
return static_cast<level>(_rc.acknowledge_level());
131+
}
122132

123133
///
124134
/// Sets the read concern string. Any valid read concern string (e.g. "local",
@@ -129,8 +139,9 @@ class read_concern {
129139
/// @param rc_string
130140
/// The read concern string.
131141
///
132-
MONGOCXX_ABI_EXPORT_CDECL(void)
133-
acknowledge_string(bsoncxx::v_noabi::stdx::string_view rc_string);
142+
void acknowledge_string(bsoncxx::v1::stdx::string_view rc_string) {
143+
_rc.acknowledge_string(rc_string);
144+
}
134145

135146
///
136147
/// Gets the current read concern string.
@@ -140,40 +151,56 @@ class read_concern {
140151
///
141152
/// @return The read concern string.
142153
///
143-
MONGOCXX_ABI_EXPORT_CDECL(bsoncxx::v_noabi::stdx::string_view) acknowledge_string() const;
154+
bsoncxx::v1::stdx::string_view acknowledge_string() const {
155+
auto ret = _rc.acknowledge_string();
156+
if (ret.empty()) {
157+
ret = "";
158+
}
159+
return ret;
160+
}
144161

145162
///
146163
/// Gets the document form of this read_concern.
147164
///
148165
/// @return
149166
/// Document representation of this read_concern.
150167
///
151-
MONGOCXX_ABI_EXPORT_CDECL(bsoncxx::v_noabi::document::value) to_document() const;
168+
bsoncxx::v_noabi::document::value to_document() const {
169+
return bsoncxx::v_noabi::from_v1(_rc.to_document());
170+
}
152171

153172
///
154173
/// @relates mongocxx::v_noabi::read_concern
155174
///
156175
/// Compares two read_concern objects for (in)-equality.
157176
///
158177
/// @{
159-
friend MONGOCXX_ABI_EXPORT_CDECL(bool) operator==(read_concern const&, read_concern const&);
160-
friend MONGOCXX_ABI_EXPORT_CDECL(bool) operator!=(read_concern const&, read_concern const&);
178+
friend bool operator==(read_concern const& lhs, read_concern const& rhs) {
179+
return lhs.acknowledge_level() == rhs.acknowledge_level();
180+
}
181+
182+
friend bool operator!=(read_concern const& lhs, read_concern const& rhs) {
183+
return !(lhs == rhs);
184+
}
161185
/// @}
162186
///
163187

164-
private:
165-
friend ::mongocxx::v_noabi::client;
166-
friend ::mongocxx::v_noabi::collection;
167-
friend ::mongocxx::v_noabi::database;
168-
friend ::mongocxx::v_noabi::options::transaction;
169-
friend ::mongocxx::v_noabi::uri;
170-
171-
class impl;
188+
class internal;
189+
};
172190

173-
read_concern(std::unique_ptr<impl>&& implementation);
191+
///
192+
/// Convert to the @ref mongocxx::v_noabi equivalent of `v`.
193+
///
194+
inline v_noabi::read_concern from_v1(v1::read_concern v) {
195+
return {std::move(v)};
196+
}
174197

175-
std::unique_ptr<impl> _impl;
176-
};
198+
///
199+
/// Convert to the @ref mongocxx::v1 equivalent of `v`.
200+
///
201+
inline v1::read_concern to_v1(v_noabi::read_concern v) {
202+
return v1::read_concern{std::move(v)};
203+
}
177204

178205
} // namespace v_noabi
179206
} // namespace mongocxx
@@ -184,3 +211,6 @@ class read_concern {
184211
/// @file
185212
/// Provides @ref mongocxx::v_noabi::read_concern.
186213
///
214+
/// @par Includes
215+
/// - @ref mongocxx/v1/read_concern.hpp
216+
///

src/mongocxx/lib/mongocxx/v1/read_concern.cpp

Lines changed: 156 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,4 +12,159 @@
1212
// See the License for the specific language governing permissions and
1313
// limitations under the License.
1414

15-
#include <mongocxx/v1/read_concern.hpp>
15+
#include <mongocxx/v1/read_concern.hh>
16+
17+
//
18+
19+
#include <bsoncxx/v1/document/value.hpp>
20+
#include <bsoncxx/v1/stdx/string_view.hpp>
21+
22+
#include <cstring>
23+
#include <string>
24+
#include <unordered_map>
25+
26+
#include <bsoncxx/private/bson.hh>
27+
28+
#include <mongocxx/private/mongoc.hh>
29+
#include <mongocxx/private/scoped_bson.hh>
30+
#include <mongocxx/private/utility.hh>
31+
32+
namespace mongocxx {
33+
namespace v1 {
34+
35+
namespace {
36+
37+
mongoc_read_concern_t* to_mongoc(void* ptr) {
38+
return static_cast<mongoc_read_concern_t*>(ptr);
39+
}
40+
41+
} // namespace
42+
43+
read_concern::~read_concern() {
44+
libmongoc::read_concern_destroy(to_mongoc(_impl));
45+
}
46+
47+
read_concern::read_concern(read_concern&& other) noexcept : _impl{exchange(other._impl, nullptr)} {}
48+
49+
read_concern& read_concern::operator=(read_concern&& other) noexcept {
50+
if (this != &other) {
51+
libmongoc::read_concern_destroy(to_mongoc(exchange(_impl, exchange(other._impl, nullptr))));
52+
}
53+
return *this;
54+
}
55+
56+
read_concern::read_concern(read_concern const& other) : _impl{libmongoc::read_concern_copy(to_mongoc(other._impl))} {}
57+
58+
read_concern& read_concern::operator=(read_concern const& other) {
59+
if (this != &other) {
60+
libmongoc::read_concern_destroy(
61+
to_mongoc(exchange(_impl, libmongoc::read_concern_copy(to_mongoc(other._impl)))));
62+
}
63+
return *this;
64+
}
65+
66+
read_concern::read_concern() : _impl{libmongoc::read_concern_new()} {}
67+
68+
read_concern& read_concern::acknowledge_level(level v) {
69+
// Return value is always true: no input validation by mongoc.
70+
switch (v) {
71+
case level::k_local:
72+
(void)libmongoc::read_concern_set_level(to_mongoc(_impl), MONGOC_READ_CONCERN_LEVEL_LOCAL);
73+
break;
74+
case level::k_majority:
75+
(void)libmongoc::read_concern_set_level(to_mongoc(_impl), MONGOC_READ_CONCERN_LEVEL_MAJORITY);
76+
break;
77+
case level::k_linearizable:
78+
(void)libmongoc::read_concern_set_level(to_mongoc(_impl), MONGOC_READ_CONCERN_LEVEL_LINEARIZABLE);
79+
break;
80+
81+
case level::k_server_default:
82+
(void)libmongoc::read_concern_set_level(to_mongoc(_impl), nullptr);
83+
break;
84+
85+
case level::k_available:
86+
(void)libmongoc::read_concern_set_level(to_mongoc(_impl), MONGOC_READ_CONCERN_LEVEL_AVAILABLE);
87+
break;
88+
case level::k_snapshot:
89+
(void)libmongoc::read_concern_set_level(to_mongoc(_impl), MONGOC_READ_CONCERN_LEVEL_SNAPSHOT);
90+
break;
91+
92+
default:
93+
case level::k_unknown:
94+
// Precondition violation: undocumented but well-defined behavior.
95+
(void)libmongoc::read_concern_set_level(to_mongoc(_impl), nullptr);
96+
break;
97+
}
98+
99+
return *this;
100+
}
101+
102+
read_concern::level read_concern::acknowledge_level() const {
103+
auto const level_cstr = libmongoc::read_concern_get_level(to_mongoc(_impl));
104+
105+
if (!level_cstr) {
106+
return level::k_server_default;
107+
}
108+
109+
std::unordered_map<bsoncxx::v1::stdx::string_view, level> const map = {
110+
{MONGOC_READ_CONCERN_LEVEL_LOCAL, level::k_local},
111+
{MONGOC_READ_CONCERN_LEVEL_MAJORITY, level::k_majority},
112+
{MONGOC_READ_CONCERN_LEVEL_LINEARIZABLE, level::k_linearizable},
113+
{MONGOC_READ_CONCERN_LEVEL_AVAILABLE, level::k_available},
114+
{MONGOC_READ_CONCERN_LEVEL_SNAPSHOT, level::k_snapshot},
115+
};
116+
117+
auto const iter = map.find(level_cstr);
118+
119+
return iter != map.end() ? iter->second : level::k_unknown;
120+
}
121+
122+
read_concern& read_concern::acknowledge_string(bsoncxx::v1::stdx::string_view v) {
123+
// Return value is always true: no input validation by mongoc.
124+
(void)libmongoc::read_concern_set_level(to_mongoc(_impl), v.empty() ? nullptr : std::string{v}.c_str());
125+
return *this;
126+
}
127+
128+
bsoncxx::v1::stdx::string_view read_concern::acknowledge_string() const {
129+
bsoncxx::v1::stdx::string_view ret;
130+
131+
if (auto const level_cstr = libmongoc::read_concern_get_level(to_mongoc(_impl))) {
132+
ret = bsoncxx::v1::stdx::string_view{level_cstr};
133+
}
134+
135+
return ret;
136+
}
137+
138+
bsoncxx::v1::document::value read_concern::to_document() const {
139+
scoped_bson doc;
140+
141+
if (auto const level_cstr = libmongoc::read_concern_get_level(to_mongoc(_impl))) {
142+
doc += scoped_bson{BCON_NEW("level", BCON_UTF8(level_cstr))};
143+
}
144+
145+
return std::move(doc).value();
146+
}
147+
148+
bool operator==(read_concern const& lhs, read_concern const& rhs) {
149+
auto const lhs_cstr = libmongoc::read_concern_get_level(to_mongoc(lhs._impl));
150+
auto const rhs_cstr = libmongoc::read_concern_get_level(to_mongoc(rhs._impl));
151+
152+
if (!lhs_cstr != !rhs_cstr) {
153+
return false;
154+
}
155+
156+
return !lhs_cstr || std::strcmp(lhs_cstr, rhs_cstr) == 0;
157+
}
158+
159+
read_concern::read_concern(void* impl) : _impl{impl} {}
160+
161+
read_concern read_concern::internal::make(mongoc_read_concern_t* rc) {
162+
return {rc};
163+
}
164+
165+
mongoc_read_concern_t const* read_concern::internal::as_mongoc(read_concern const& self) {
166+
return to_mongoc(self._impl);
167+
}
168+
169+
} // namespace v1
170+
} // namespace mongocxx

0 commit comments

Comments
 (0)