fb-cpp 0.0.2
A modern C++ wrapper for the Firebird database API
Loading...
Searching...
No Matches
AttachmentPool.h
1/*
2 * MIT License
3 *
4 * Copyright (c) 2026 Adriano dos Santos Fernandes
5 *
6 * Permission is hereby granted, free of charge, to any person obtaining a copy
7 * of this software and associated documentation files (the "Software"), to deal
8 * in the Software without restriction, including without limitation the rights
9 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10 * copies of the Software, and to permit persons to whom the Software is
11 * furnished to do so, subject to the following conditions:
12 *
13 * The above copyright notice and this permission notice shall be included in all
14 * copies or substantial portions of the Software.
15 *
16 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
22 * SOFTWARE.
23 */
24
25#ifndef FBCPP_ATTACHMENT_POOL_H
26#define FBCPP_ATTACHMENT_POOL_H
27
28#include "Attachment.h"
29#include "fb-cpp-export.h"
30#include "fb-api.h"
31#include <cassert>
32#include <chrono>
33#include <condition_variable>
34#include <cstddef>
35#include <deque>
36#include <memory>
37#include <mutex>
38#include <optional>
39#include <string>
40#include <vector>
41
42
46namespace fbcpp
47{
48 class Client;
49
54 {
55 public:
60 {
61 return attachmentOptions;
62 }
63
70 {
71 attachmentOptions = value;
72 return *this;
73 }
74
78 std::size_t getMinSize() const
79 {
80 return minSize;
81 }
82
87 {
88 minSize = value;
89 return *this;
90 }
91
95 std::size_t getMaxSize() const
96 {
97 return maxSize;
98 }
99
104 {
105 maxSize = value;
106 return *this;
107 }
108
112 std::chrono::milliseconds getAcquireTimeout() const
113 {
114 return acquireTimeout;
115 }
116
120 AttachmentPoolOptions& setAcquireTimeout(std::chrono::milliseconds value)
121 {
122 acquireTimeout = value;
123 return *this;
124 }
125
129 const std::optional<std::chrono::milliseconds>& getIdleTimeout() const
130 {
131 return idleTimeout;
132 }
133
138 AttachmentPoolOptions& setIdleTimeout(std::chrono::milliseconds value)
139 {
140 idleTimeout = value;
141 return *this;
142 }
143
147 const std::optional<std::chrono::milliseconds>& getMaxLifetime() const
148 {
149 return maxLifetime;
150 }
151
155 AttachmentPoolOptions& setMaxLifetime(std::chrono::milliseconds value)
156 {
157 maxLifetime = value;
158 return *this;
159 }
160
165 {
166 return validateOnAcquire;
167 }
168
173 {
174 validateOnAcquire = value;
175 return *this;
176 }
177
183 {
184 return sessionResetOnRelease;
185 }
186
192 {
193 sessionResetOnRelease = value;
194 return *this;
195 }
196
197 private:
198 AttachmentOptions attachmentOptions;
199 std::size_t minSize = 0u;
200 std::size_t maxSize = 10u;
201 std::chrono::milliseconds acquireTimeout{30000};
202 std::optional<std::chrono::milliseconds> idleTimeout;
203 std::optional<std::chrono::milliseconds> maxLifetime;
204 bool validateOnAcquire = true;
205 bool sessionResetOnRelease = false;
206 };
207
208
209 namespace impl
210 {
215 struct AttachmentPoolEntry final
216 {
217 std::unique_ptr<Attachment> attachment;
218 std::chrono::steady_clock::time_point createdAt;
219 std::chrono::steady_clock::time_point lastReturnedAt;
220 };
221 } // namespace impl
222
223
224 class AttachmentPool;
225
231 class FB_CPP_EXPORT PooledAttachment final
232 {
233 friend class AttachmentPool;
234
235 private:
236 explicit PooledAttachment(AttachmentPool& pool, impl::AttachmentPoolEntry& entry) noexcept
237 : pool{&pool},
238 entry{&entry}
239 {
240 }
241
242 public:
248 : pool{o.pool},
249 entry{o.entry}
250 {
251 o.pool = nullptr;
252 o.entry = nullptr;
253 }
254
260 {
261 if (this != &o)
262 {
263 release();
264
265 pool = o.pool;
266 entry = o.entry;
267 o.pool = nullptr;
268 o.entry = nullptr;
269 }
270
271 return *this;
272 }
273
274 PooledAttachment(const PooledAttachment&) = delete;
275 PooledAttachment& operator=(const PooledAttachment&) = delete;
276
281 {
282 try
283 {
284 release();
285 }
286 catch (...)
287 {
288 // swallow
289 }
290 }
291
292 public:
296 bool isValid() const noexcept
297 {
298 return entry != nullptr;
299 }
300
304 Attachment& get() noexcept
305 {
306 assert(entry);
307 return *entry->attachment;
308 }
309
310 Attachment& operator*() noexcept
311 {
312 return get();
313 }
314
315 Attachment* operator->() noexcept
316 {
317 return &get();
318 }
319
324 void release();
325
326 private:
327 AttachmentPool* pool;
328 impl::AttachmentPoolEntry* entry;
329 };
330
338 class FB_CPP_EXPORT AttachmentPool final
339 {
340 friend class PooledAttachment;
341
342 public:
347 explicit AttachmentPool(Client& client, std::string uri, const AttachmentPoolOptions& options = {});
348
353 ~AttachmentPool() noexcept;
354
355 AttachmentPool(const AttachmentPool&) = delete;
356 AttachmentPool& operator=(const AttachmentPool&) = delete;
357
358 AttachmentPool(AttachmentPool&&) = delete;
359 AttachmentPool& operator=(AttachmentPool&&) = delete;
360
361 public:
365 Client& getClient() noexcept
366 {
367 return *client;
368 }
369
373 const std::string& getUri() const noexcept
374 {
375 return uri;
376 }
377
381 const AttachmentPoolOptions& getOptions() const noexcept
382 {
383 return options;
384 }
385
389 std::size_t size();
390
394 std::size_t availableCount();
395
399 std::size_t inUseCount();
400
405 PooledAttachment acquire();
406
411 std::optional<PooledAttachment> tryAcquire();
412
417 void close();
418
419 private:
420 std::optional<PooledAttachment> acquireImpl(bool throwOnFailure);
421 void evictLocked(std::unique_lock<std::mutex>& lock);
422 void release(impl::AttachmentPoolEntry& entry) noexcept;
423
424 private:
425 Client* client;
426 std::string uri;
427 AttachmentPoolOptions options;
428 std::vector<std::unique_ptr<impl::AttachmentPoolEntry>> entries;
429 std::deque<impl::AttachmentPoolEntry*> available;
430 std::size_t inUse = 0u;
431 std::size_t pending = 0u;
432 bool closed = false;
433 std::mutex mutex;
434 std::condition_variable availableCondition;
435 };
436
438 {
439 if (!entry)
440 return;
441
442 const auto poolPtr = pool;
443 const auto entryPtr = entry;
444
445 pool = nullptr;
446 entry = nullptr;
447
448 poolPtr->release(*entryPtr);
449 }
450} // namespace fbcpp
451
452
453#endif // FBCPP_ATTACHMENT_POOL_H
Represents options used when creating an Attachment object.
Definition Attachment.h:55
Represents options used when creating an AttachmentPool object.
bool getSessionResetOnRelease() const
Returns whether a connection has its session reset (via ALTER SESSION RESET) before being returned to...
const std::optional< std::chrono::milliseconds > & getIdleTimeout() const
Returns the maximum time a connection may stay idle in the pool before being closed.
AttachmentPoolOptions & setValidateOnAcquire(bool value)
Sets whether a connection is validated (via ping) before being handed out by acquire().
AttachmentPoolOptions & setIdleTimeout(std::chrono::milliseconds value)
Sets the maximum time a connection may stay idle in the pool before being closed.
std::size_t getMaxSize() const
Returns the maximum number of connections the pool may create.
bool getValidateOnAcquire() const
Returns whether a connection is validated (via ping) before being handed out by acquire().
AttachmentPoolOptions & setSessionResetOnRelease(bool value)
Sets whether a connection has its session reset (via ALTER SESSION RESET) before being returned to th...
const std::optional< std::chrono::milliseconds > & getMaxLifetime() const
Returns the maximum lifetime of a connection, regardless of usage.
std::chrono::milliseconds getAcquireTimeout() const
Returns how long acquire() waits for a connection to become available before throwing.
AttachmentPoolOptions & setAttachmentOptions(const AttachmentOptions &value)
Sets the options used to create each pooled Attachment.
AttachmentPoolOptions & setMaxLifetime(std::chrono::milliseconds value)
Sets the maximum lifetime of a connection, regardless of usage.
AttachmentPoolOptions & setMinSize(std::size_t value)
Sets the minimum number of connections kept warm by the pool.
const AttachmentOptions & getAttachmentOptions() const
Returns the options used to create each pooled Attachment.
AttachmentPoolOptions & setMaxSize(std::size_t value)
Sets the maximum number of connections the pool may create.
std::size_t getMinSize() const
Returns the minimum number of connections kept warm by the pool.
AttachmentPoolOptions & setAcquireTimeout(std::chrono::milliseconds value)
Sets how long acquire() waits for a connection to become available before throwing.
Represents a thread-safe pool of Attachment objects connected to the same database.
const AttachmentPoolOptions & getOptions() const noexcept
Returns the options used to create this AttachmentPool object.
const std::string & getUri() const noexcept
Returns the database URI this pool connects to.
Client & getClient() noexcept
Returns the Client object reference used to create this AttachmentPool object.
Represents a connection to a Firebird database.
Definition Attachment.h:219
Represents a Firebird client library instance.
Definition Client.h:54
RAII lease for an Attachment borrowed from an AttachmentPool.
bool isValid() const noexcept
Returns whether this object currently holds a leased Attachment.
~PooledAttachment() noexcept
Returns the Attachment to the pool, unless it was already released.
void release()
Returns the leased Attachment to the pool immediately.
PooledAttachment & operator=(PooledAttachment &&o) noexcept
Move assignment.
Attachment & get() noexcept
Returns the leased Attachment.
PooledAttachment(PooledAttachment &&o) noexcept
Move constructor.
fb-cpp namespace.
Definition Attachment.h:46