Stroika Library 3.0d23
 
Loading...
Searching...
No Matches
MongoDBClient.h
1/*
2 * Copyright(c) Sophist Solutions, Inc. 1990-2026. All rights reserved
3 */
4#ifndef _Stroika_Foundation_Database_Document_MongoDBClient_h_
5#define _Stroika_Foundation_Database_Document_MongoDBClient_h_ 1
6
7#include "Stroika/Foundation/StroikaPreComp.h"
8
9#if qStroika_HasComponent_mongocxxdriver
10// forward declare so we can expose these interfaces to code which #includes the appropriate file, but not force
11// its inclusion just to use the MongoDBClient
12namespace mongocxx::v_noabi {
13 class client;
14 class pool;
15 class instance;
16}
17namespace mongocxx {
18 using ::mongocxx::v_noabi::client;
19 using ::mongocxx::v_noabi::instance;
20 using ::mongocxx::v_noabi::pool;
21}
22#endif
23
29
30/*
31 * \file
32 *
33 * \note Code-Status: <a href="Code-Status.md#Alpha">Alpha</a>
34 *
35 * TODO:
36 *
37 */
38
39/*
40@CONFIGVAR: DqStroika_HasComponent_mongocxxdriver
41@DESCRIPTION: Defines if Stroika is built supporting mongo-cxx-driver
42*/
43#ifndef qStroika_HasComponent_mongocxxdriver
44#error "qStroika_HasComponent_mongocxxdriver should normally be defined indirectly by StroikaConfig.h"
45#endif
46
47namespace Stroika::Foundation::Database::Document::MongoDBClient {
48
49#if qStroika_HasComponent_mongocxxdriver
50
51 /**
52 * \brief must be instantiated after main, but before any use of MongoCXX library methods, and destroyed after all such methods
53 *
54 * \pre Debug::AppearsDuringMainLifetime ()
55 *
56 * From mongo-cxx-driver source code:
57 * Exactly one instance must be created in a given program. Not constructing an instance or
58 * constructing more than one instance in a program are errors, even if the multiple instances have
59 * non-overlapping lifetimes.
60 *
61 * To allow Stroika code to activate and deactivate (rarely but possibly useful) - an optional flag is provided, and
62 * if set allowReactivation=true, then the underlying mongocxx instance object not destroyed until application end,
63 * so that you can re-activate. JUST IGNORE this for hte most part and stick with the default!
64 */
65 struct Activator final {
66 enum AllowReactivateFlag {
67 eAllowReactivateFlag
68 };
69 Activator ();
70 Activator (AllowReactivateFlag);
71 ~Activator ();
72
73 private:
74 bool fAllowReactivation_;
75 static unique_ptr<mongocxx::instance> sMongoInstance_;
76 };
77
78 /**
79 * \brief optionally pool mongodb connections (to a given server). Create the object and pass it
80 * as 'target' option to Connection::New()...
81 *
82 * \note \em Thread-Safety <a href="Thread-Safety.md#Internally-Synchronized-Thread-Safety">Internally-Synchronized-Thread-Safety</a>
83 */
84 class ConnectionPool final {
85 public:
86 ConnectionPool () = delete;
87 ConnectionPool (const ConnectionPool&) = default;
88 ConnectionPool (shared_ptr<mongocxx::pool>&& poolRep);
89 ConnectionPool (const String& connectionString);
90 ~ConnectionPool () = default;
91
92 public:
93 /**
94 */
95 nonvirtual mongocxx::pool& PeekPool () const;
96
97 private:
98 // shared_ptr is internally synchronized for copies / control block updates (refCnt) - and mongocxx::pool internally synrchonized
99 shared_ptr<mongocxx::pool> fPool_;
100 };
101
102 namespace AdminConnection {
103 class IRep;
104
105 /**
106 * \note \em Thread-Safety <a href="Thread-Safety.md#C++-Standard-Thread-Safety">C++-Standard-Thread-Safety</a>
107 */
108 class Ptr : public shared_ptr<IRep> {
109 private:
110 using inherited = shared_ptr<IRep>;
111
112 public:
113 /**
114 */
115 Ptr () noexcept = default;
116 Ptr (const Ptr& src) noexcept = default;
117 Ptr (const shared_ptr<IRep>& src) noexcept;
118 Ptr (nullptr_t) noexcept;
119
120 public:
121 ~Ptr () noexcept = default;
122
123 public:
124 /**
125 */
126 nonvirtual Document run_command (const Document& v);
127
128 public:
129 /**
130 */
131 nonvirtual mongocxx::client& GetClientRef ();
132
133 public:
134 /**
135 */
136 nonvirtual Set<String> GetDatabases ();
137
138 public:
139 /**
140 */
141 nonvirtual void DropDatabase (const String& dbName);
142
143 public:
144 /**
145 */
146 nonvirtual void CreateDatabase (const String& dbName);
147 };
148
149 /**
150 * \note \em Thread-Safety <a href="Thread-Safety.md#C++-Standard-Thread-Safety">C++-Standard-Thread-Safety</a>
151 */
152 class IRep {
153 public:
154 virtual Document run_command (const Document& v) = 0;
155
156 public:
157 virtual mongocxx::client& GetClientRef () = 0;
158
159 public:
160 virtual Set<String> GetDatabases () = 0;
161
162 public:
163 virtual void DropDatabase (const String& dbName) = 0;
164
165 public:
166 virtual void CreateDatabase (const String& dbName) = 0;
167 };
168
169 /**
170 * These are options used to create a database Connection::Ptr object (with Connection::New).
171 *
172 * Since this is also how you create a database, in a sense, its those options too.
173 */
174 struct Options final : Database::Document::Connection::Options {
175 /**
176 * \brief use eInternallySynchronized to make letter (connection object) internally synchronized
177 *
178 * \note The remote database is always 'synchronized' / threadsafe.
179 *
180 * \note if set eNotKnownInternallySynchronized (the default), in debug mode, the system uses AssertExternallySynchronizedMutex
181 * to check for unsafe thread usage.
182 */
183 Execution::InternallySynchronized fInternallySynchronizedLetter{Execution::eNotKnownInternallySynchronized};
184
185 /**
186 * @brief see https://www.mongodb.com/docs/manual/reference/connection-string/
187 */
188 variant<String, ConnectionPool> fConnectionTarget;
189 };
190
191 /**
192 * \note produces unsynchronized reps - so must be externally synchronized
193 */
194 Ptr New (const Options& options);
195 }
196
197 namespace Connection {
198
199 using namespace Database::Document::Connection;
200
201 class IRep;
202
203 /**
204 * These are options used to create a database Connection::Ptr object (with Connection::New).
205 *
206 * Since this is also how you create a database, in a sense, its those options too.
207 */
208 struct Options final : Database::Document::Connection::Options {
209 /**
210 * \brief use eInternallySynchronized to make letter (connection object) internally synchronized
211 *
212 * \note The remote database is always 'synchronized' / threadsafe.
213 *
214 * \note if set eNotKnownInternallySynchronized (the default), in debug mode, the system uses AssertExternallySynchronizedMutex
215 * to check for unsafe thread usage.
216 */
217 Execution::InternallySynchronized fInternallySynchronizedLetter{Execution::eNotKnownInternallySynchronized};
218
219 /**
220 * @brief see https://www.mongodb.com/docs/manual/reference/connection-string/
221 */
222 variant<String, ConnectionPool> fConnectionTarget;
223
224 /**
225 * Connection string does not contain database name. Different from Mongo API, we choose to require a database name
226 * in the connection options. Use AdminConnection to operate on server itself, not a particular database.
227 */
228 String fDatabase;
229 };
230
231 /**
232 * Connection provides an API for accessing a particular MongoDB database.
233 *
234 * A new Connection::Ptr is typically created MongoDBClient::Connection::New()
235 */
236 class Ptr : public Database::Document::Connection::Ptr {
237 private:
238 using inherited = Database::Document::Connection::Ptr;
239
240 public:
241 /**
242 */
243 Ptr () noexcept = default;
244 Ptr (const Ptr& src);
245 Ptr (const shared_ptr<IRep>& src);
246 Ptr (nullptr_t) noexcept;
247
248 public:
249 ~Ptr () = default;
250
251 public:
252 /**
253 */
254 nonvirtual Ptr& operator= (const Ptr& src);
255 nonvirtual Ptr& operator= (Ptr&& src) noexcept;
256
257 public:
258 /**
259 */
260 nonvirtual IRep* operator->() const noexcept;
261
262 public:
263 /**
264 */
265 nonvirtual mongocxx::client& GetClientRef ();
266 };
267
268 /**
269 * \note produces unsynchronized reps - so must be externally synchronized
270 */
271 Ptr New (const Options& options);
272
273 /**
274 * Connection provides an API for accessing an MongoDBClient database.
275 *
276 * Typically don't use this directly, but use Connection::Ptr, a smart ptr wrapper on this interface.
277 */
278 class IRep : public Database::Document::Connection::IRep {
279 public:
280 virtual mongocxx::client& GetClientRef () = 0;
281 };
282
283 };
284
285 /**
286 * @todo NYI
287 */
288 class Transaction : public Database::Document::Transaction {
289 private:
290 using inherited = Database::Document::Transaction;
291
292 public:
293 /**
294 */
295 Transaction () = delete;
296 Transaction (const Connection::Ptr& db);
297 Transaction (const Transaction&) = delete;
298
299 private:
300 struct MyRep_;
301 };
302#endif
303
304}
305
306/*
307 ********************************************************************************
308 ***************************** Implementation Details ***************************
309 ********************************************************************************
310 */
311#include "MongoDBClient.inl"
312
313#endif /*_Stroika_Foundation_Database_Document_MongoDBClient_h_*/
Mapping< String, VariantValue > Document
Definition Document.h:28