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-api.h"
30#include <cassert>
31#include <chrono>
32#include <condition_variable>
33#include <cstddef>
34#include <deque>
35#include <memory>
36#include <mutex>
37#include <optional>
38#include <string>
39#include <vector>
40
41
45namespace fbcpp
46{
47 class Client;
48
53 {
54 public:
59 {
60 return attachmentOptions;
61 }
62
69 {
70 attachmentOptions = value;
71 return *this;
72 }
73
77 std::size_t getMinSize() const
78 {
79 return minSize;
80 }
81
86 {
87 minSize = value;
88 return *this;
89 }
90
94 std::size_t getMaxSize() const
95 {
96 return maxSize;
97 }
98
103 {
104 maxSize = value;
105 return *this;
106 }
107
111 std::chrono::milliseconds getAcquireTimeout() const
112 {
113 return acquireTimeout;
114 }
115
119 AttachmentPoolOptions& setAcquireTimeout(std::chrono::milliseconds value)
120 {
121 acquireTimeout = value;
122 return *this;
123 }
124
128 const std::optional<std::chrono::milliseconds>& getIdleTimeout() const
129 {
130 return idleTimeout;
131 }
132
137 AttachmentPoolOptions& setIdleTimeout(std::chrono::milliseconds value)
138 {
139 idleTimeout = value;
140 return *this;
141 }
142
146 const std::optional<std::chrono::milliseconds>& getMaxLifetime() const
147 {
148 return maxLifetime;
149 }
150
154 AttachmentPoolOptions& setMaxLifetime(std::chrono::milliseconds value)
155 {
156 maxLifetime = value;
157 return *this;
158 }
159
164 {
165 return validateOnAcquire;
166 }
167
172 {
173 validateOnAcquire = value;
174 return *this;
175 }
176
182 {
183 return sessionResetOnRelease;
184 }
185
191 {
192 sessionResetOnRelease = value;
193 return *this;
194 }
195
196 private:
197 AttachmentOptions attachmentOptions;
198 std::size_t minSize = 0u;
199 std::size_t maxSize = 10u;
200 std::chrono::milliseconds acquireTimeout{30000};
201 std::optional<std::chrono::milliseconds> idleTimeout;
202 std::optional<std::chrono::milliseconds> maxLifetime;
203 bool validateOnAcquire = true;
204 bool sessionResetOnRelease = false;
205 };
206
207
208 namespace impl
209 {
214 struct AttachmentPoolEntry final
215 {
216 std::unique_ptr<Attachment> attachment;
217 std::chrono::steady_clock::time_point createdAt;
218 std::chrono::steady_clock::time_point lastReturnedAt;
219 };
220 } // namespace impl
221
222
223 class AttachmentPool;
224
231 {
232 friend class AttachmentPool;
233
234 private:
235 explicit PooledAttachment(AttachmentPool& pool, impl::AttachmentPoolEntry& entry) noexcept
236 : pool{&pool},
237 entry{&entry}
238 {
239 }
240
241 public:
247 : pool{o.pool},
248 entry{o.entry}
249 {
250 o.pool = nullptr;
251 o.entry = nullptr;
252 }
253
259 {
260 if (this != &o)
261 {
262 release();
263
264 pool = o.pool;
265 entry = o.entry;
266 o.pool = nullptr;
267 o.entry = nullptr;
268 }
269
270 return *this;
271 }
272
273 PooledAttachment(const PooledAttachment&) = delete;
275
280 {
281 try
282 {
283 release();
284 }
285 catch (...)
286 {
287 // swallow
288 }
289 }
290
291 public:
296 {
297 return entry != nullptr;
298 }
299
304 {
305 assert(entry);
306 return *entry->attachment;
307 }
308
309 Attachment& operator*() noexcept
310 {
311 return get();
312 }
313
314 Attachment* operator->() noexcept
315 {
316 return &get();
317 }
318
323 void release();
324
325 private:
326 AttachmentPool* pool;
327 impl::AttachmentPoolEntry* entry;
328 };
329
337 class AttachmentPool final
338 {
339 friend class PooledAttachment;
340
341 public:
346 explicit AttachmentPool(Client& client, std::string uri, const AttachmentPoolOptions& options = {});
347
352 ~AttachmentPool() noexcept;
353
354 AttachmentPool(const AttachmentPool&) = delete;
355 AttachmentPool& operator=(const AttachmentPool&) = delete;
356
357 AttachmentPool(AttachmentPool&&) = delete;
358 AttachmentPool& operator=(AttachmentPool&&) = delete;
359
360 public:
364 Client& getClient() noexcept
365 {
366 return *client;
367 }
368
372 const std::string& getUri() const noexcept
373 {
374 return uri;
375 }
376
380 const AttachmentPoolOptions& getOptions() const noexcept
381 {
382 return options;
383 }
384
388 std::size_t size();
389
393 std::size_t availableCount();
394
398 std::size_t inUseCount();
399
405
410 std::optional<PooledAttachment> tryAcquire();
411
416 void close();
417
418 private:
419 std::optional<PooledAttachment> acquireImpl(bool throwOnFailure);
420 void evictLocked(std::unique_lock<std::mutex>& lock);
421 void release(impl::AttachmentPoolEntry& entry) noexcept;
422
423 private:
424 Client* client;
425 std::string uri;
426 AttachmentPoolOptions options;
427 std::vector<std::unique_ptr<impl::AttachmentPoolEntry>> entries;
428 std::deque<impl::AttachmentPoolEntry*> available;
429 std::size_t inUse = 0u;
430 std::size_t pending = 0u;
431 bool closed = false;
432 std::mutex mutex;
433 std::condition_variable availableCondition;
434 };
435
437 {
438 if (!entry)
439 return;
440
441 const auto poolPtr = pool;
442 const auto entryPtr = entry;
443
444 pool = nullptr;
445 entry = nullptr;
446
447 poolPtr->release(*entryPtr);
448 }
449} // namespace fbcpp
450
451
452#endif // FBCPP_ATTACHMENT_POOL_H
Represents options used when creating an Attachment object.
Definition Attachment.h:54
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.
std::size_t inUseCount()
Returns the number of connections currently leased out by the pool.
PooledAttachment acquire()
Acquires a connection from the pool, creating one if needed and allowed by getMaxSize().
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.
void close()
Closes every available connection and marks the pool as closed.
Client & getClient() noexcept
Returns the Client object reference used to create this AttachmentPool object.
std::size_t availableCount()
Returns the number of connections currently available (not leased) in the pool.
~AttachmentPool() noexcept
Closes every idle connection in the pool.
std::size_t size()
Returns the total number of connections currently created by the pool (in use plus available).
std::optional< PooledAttachment > tryAcquire()
Attempts to acquire a connection from the pool without throwing.
Represents a connection to a Firebird database.
Definition Attachment.h:218
Represents a Firebird client library instance.
Definition Client.h:53
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:45