Skip to content

Commit 458ec11

Browse files
committed
Set up the database under the same synchronization lock as opening it
1 parent c3dfa76 commit 458ec11

File tree

4 files changed

+90
-48
lines changed

4 files changed

+90
-48
lines changed

dev/connection_holder.h

Lines changed: 30 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66
#ifdef SQLITE_ORM_CPP20_SEMAPHORE_SUPPORTED
77
#include <semaphore>
88
#endif
9+
#include <functional> // std::function
910
#include <string> // std::string
1011
#endif
1112

@@ -42,7 +43,15 @@ namespace sqlite_orm {
4243
std::binary_semaphore& sync;
4344
};
4445

45-
connection_holder(std::string filename) : filename(std::move(filename)) {}
46+
connection_holder(std::string filename, bool openedForeverHint, std::function<void(sqlite3*)> onAfterOpen) :
47+
filename(std::move(filename)), _openedForeverHint{openedForeverHint},
48+
_onAfterOpen{std::move(onAfterOpen)} {}
49+
50+
connection_holder(const connection_holder&) = delete;
51+
52+
connection_holder(const connection_holder& other, std::function<void(sqlite3*)> onAfterOpen) :
53+
filename{other.filename}, _openedForeverHint{other._openedForeverHint},
54+
_onAfterOpen{std::move(onAfterOpen)} {}
4655

4756
void retain() {
4857
const maybe_lock maybeLock{this->_sync, !this->_openedForeverHint};
@@ -54,12 +63,16 @@ namespace sqlite_orm {
5463
return;
5564
}
5665

57-
// first one opens the connection.
66+
// first one opens and sets up the connection.
5867

5968
if (int rc = sqlite3_open(this->filename.c_str(), &this->db); rc != SQLITE_OK)
6069
[[unlikely]] /*possible, but unexpected*/ {
6170
throw_translated_sqlite_error(this->db);
6271
}
72+
73+
if (this->_onAfterOpen) {
74+
this->_onAfterOpen(this->db);
75+
}
6376
}
6477

6578
void release() {
@@ -103,13 +116,21 @@ namespace sqlite_orm {
103116
sqlite3* db = nullptr;
104117

105118
private:
106-
std::binary_semaphore _sync{1};
107119
const bool _openedForeverHint = false;
120+
const std::function<void(sqlite3* db)> _onAfterOpen;
121+
std::binary_semaphore _sync{1};
108122
std::atomic_int _retain_count{};
109123
};
110124
#else
111125
struct connection_holder {
112-
connection_holder(std::string filename) : filename(std::move(filename)) {}
126+
connection_holder(std::string filename,
127+
bool /*openedForeverHint*/,
128+
std::function<void(sqlite3*)> onAfterOpen) :
129+
filename(std::move(filename)), _onAfterOpen{std::move(onAfterOpen)} {}
130+
131+
connection_holder(const connection_holder&) = delete;
132+
connection_holder(const connection_holder& other, std::function<void(sqlite3*)> onAfterOpen) :
133+
filename{other.filename}, _onAfterOpen{std::move(onAfterOpen)} {}
113134

114135
void retain() {
115136
// first one opens the connection.
@@ -121,6 +142,10 @@ namespace sqlite_orm {
121142
throw_translated_sqlite_error(this->db);
122143
}
123144
}
145+
146+
if (this->_onAfterOpen) {
147+
this->_onAfterOpen(this->db);
148+
}
124149
}
125150

126151
void release() {
@@ -154,6 +179,7 @@ namespace sqlite_orm {
154179
sqlite3* db = nullptr;
155180

156181
private:
182+
const std::function<void(sqlite3* db)> _onAfterOpen;
157183
std::atomic_int _retain_count{};
158184
};
159185
#endif

dev/pragma.h

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -258,11 +258,12 @@ namespace sqlite_orm {
258258
}
259259

260260
void set_pragma_impl(const std::string& query, sqlite3* db = nullptr) {
261-
auto con = this->get_connection();
262-
if (db == nullptr) {
263-
db = con.get();
261+
if (db) {
262+
perform_void_exec(db, query);
263+
} else {
264+
auto con = this->get_connection();
265+
perform_void_exec(con.get(), query);
264266
}
265-
perform_void_exec(db, query);
266267
}
267268
};
268269
}

dev/storage_base.h

Lines changed: 10 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -295,9 +295,6 @@ namespace sqlite_orm {
295295
void open_forever() {
296296
this->isOpenedForever = true;
297297
this->connection->retain();
298-
if (1 == this->connection->retain_count()) {
299-
this->on_open_internal(this->connection->get());
300-
}
301298
}
302299

303300
/**
@@ -610,7 +607,7 @@ namespace sqlite_orm {
610607
}
611608

612609
backup_t make_backup_to(const std::string& filename) {
613-
auto holder = std::make_unique<connection_holder>(filename);
610+
auto holder = std::make_unique<connection_holder>(filename, true, nullptr);
614611
connection_ref conRef{*holder};
615612
return {conRef, "main", this->get_connection(), "main", std::move(holder)};
616613
}
@@ -620,7 +617,7 @@ namespace sqlite_orm {
620617
}
621618

622619
backup_t make_backup_from(const std::string& filename) {
623-
auto holder = std::make_unique<connection_holder>(filename);
620+
auto holder = std::make_unique<connection_holder>(filename, true, nullptr);
624621
connection_ref conRef{*holder};
625622
return {this->get_connection(), "main", conRef, "main", std::move(holder)};
626623
}
@@ -668,22 +665,25 @@ namespace sqlite_orm {
668665
pragma(std::bind(&storage_base::get_connection, this)),
669666
limit(std::bind(&storage_base::get_connection, this)),
670667
inMemory(filename.empty() || filename == ":memory:"),
671-
connection(std::make_unique<connection_holder>(std::move(filename))),
668+
connection(std::make_unique<connection_holder>(
669+
std::move(filename),
670+
inMemory,
671+
std::bind(&storage_base::on_open_internal, this, std::placeholders::_1))),
672672
cachedForeignKeysCount(foreignKeysCount) {
673673
if (this->inMemory) {
674674
this->connection->retain();
675-
this->on_open_internal(this->connection->get());
676675
}
677676
}
678677

679678
storage_base(const storage_base& other) :
680679
on_open(other.on_open), pragma(std::bind(&storage_base::get_connection, this)),
681680
limit(std::bind(&storage_base::get_connection, this)), inMemory(other.inMemory),
682-
connection(std::make_unique<connection_holder>(other.connection->filename)),
681+
connection(std::make_unique<connection_holder>(
682+
*other.connection,
683+
std::bind(&storage_base::on_open_internal, this, std::placeholders::_1))),
683684
cachedForeignKeysCount(other.cachedForeignKeysCount) {
684685
if (this->inMemory) {
685686
this->connection->retain();
686-
this->on_open_internal(this->connection->get());
687687
}
688688
}
689689

@@ -698,18 +698,12 @@ namespace sqlite_orm {
698698

699699
void begin_transaction_internal(const std::string& query) {
700700
this->connection->retain();
701-
if (1 == this->connection->retain_count()) {
702-
this->on_open_internal(this->connection->get());
703-
}
704701
sqlite3* db = this->connection->get();
705702
perform_void_exec(db, query);
706703
}
707704

708705
connection_ref get_connection() {
709706
connection_ref res{*this->connection};
710-
if (1 == this->connection->retain_count()) {
711-
this->on_open_internal(this->connection->get());
712-
}
713707
return res;
714708
}
715709

@@ -735,7 +729,7 @@ namespace sqlite_orm {
735729
}
736730
#endif
737731
if (this->pragma.synchronous_ != -1) {
738-
this->pragma.synchronous(this->pragma.synchronous_);
732+
this->pragma.set_pragma("synchronous", this->pragma.synchronous_, db);
739733
}
740734

741735
if (this->pragma.journal_mode_ != -1) {

include/sqlite_orm/sqlite_orm.h

Lines changed: 45 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -13883,6 +13883,7 @@ namespace sqlite_orm {
1388313883
#ifdef SQLITE_ORM_CPP20_SEMAPHORE_SUPPORTED
1388413884
#include <semaphore>
1388513885
#endif
13886+
#include <functional> // std::function
1388613887
#include <string> // std::string
1388713888
#endif
1388813889

@@ -13919,7 +13920,15 @@ namespace sqlite_orm {
1391913920
std::binary_semaphore& sync;
1392013921
};
1392113922

13922-
connection_holder(std::string filename) : filename(std::move(filename)) {}
13923+
connection_holder(std::string filename, bool openedForeverHint, std::function<void(sqlite3*)> onAfterOpen) :
13924+
filename(std::move(filename)), _openedForeverHint{openedForeverHint},
13925+
_onAfterOpen{std::move(onAfterOpen)} {}
13926+
13927+
connection_holder(const connection_holder&) = delete;
13928+
13929+
connection_holder(const connection_holder& other, std::function<void(sqlite3*)> onAfterOpen) :
13930+
filename{other.filename}, _openedForeverHint{other._openedForeverHint},
13931+
_onAfterOpen{std::move(onAfterOpen)} {}
1392313932

1392413933
void retain() {
1392513934
const maybe_lock maybeLock{this->_sync, !this->_openedForeverHint};
@@ -13931,12 +13940,16 @@ namespace sqlite_orm {
1393113940
return;
1393213941
}
1393313942

13934-
// first one opens the connection.
13943+
// first one opens and sets up the connection.
1393513944

1393613945
if (int rc = sqlite3_open(this->filename.c_str(), &this->db); rc != SQLITE_OK)
1393713946
[[unlikely]] /*possible, but unexpected*/ {
1393813947
throw_translated_sqlite_error(this->db);
1393913948
}
13949+
13950+
if (this->_onAfterOpen) {
13951+
this->_onAfterOpen(this->db);
13952+
}
1394013953
}
1394113954

1394213955
void release() {
@@ -13980,13 +13993,21 @@ namespace sqlite_orm {
1398013993
sqlite3* db = nullptr;
1398113994

1398213995
private:
13983-
std::binary_semaphore _sync{1};
1398413996
const bool _openedForeverHint = false;
13997+
const std::function<void(sqlite3* db)> _onAfterOpen;
13998+
std::binary_semaphore _sync{1};
1398513999
std::atomic_int _retain_count{};
1398614000
};
1398714001
#else
1398814002
struct connection_holder {
13989-
connection_holder(std::string filename) : filename(std::move(filename)) {}
14003+
connection_holder(std::string filename,
14004+
bool /*openedForeverHint*/,
14005+
std::function<void(sqlite3*)> onAfterOpen) :
14006+
filename(std::move(filename)), _onAfterOpen{std::move(onAfterOpen)} {}
14007+
14008+
connection_holder(const connection_holder&) = delete;
14009+
connection_holder(const connection_holder& other, std::function<void(sqlite3*)> onAfterOpen) :
14010+
filename{other.filename}, _onAfterOpen{std::move(onAfterOpen)} {}
1399014011

1399114012
void retain() {
1399214013
// first one opens the connection.
@@ -13998,6 +14019,10 @@ namespace sqlite_orm {
1399814019
throw_translated_sqlite_error(this->db);
1399914020
}
1400014021
}
14022+
14023+
if (this->_onAfterOpen) {
14024+
this->_onAfterOpen(this->db);
14025+
}
1400114026
}
1400214027

1400314028
void release() {
@@ -14031,6 +14056,7 @@ namespace sqlite_orm {
1403114056
sqlite3* db = nullptr;
1403214057

1403314058
private:
14059+
const std::function<void(sqlite3* db)> _onAfterOpen;
1403414060
std::atomic_int _retain_count{};
1403514061
};
1403614062
#endif
@@ -17051,11 +17077,12 @@ namespace sqlite_orm {
1705117077
}
1705217078

1705317079
void set_pragma_impl(const std::string& query, sqlite3* db = nullptr) {
17054-
auto con = this->get_connection();
17055-
if (db == nullptr) {
17056-
db = con.get();
17080+
if (db) {
17081+
perform_void_exec(db, query);
17082+
} else {
17083+
auto con = this->get_connection();
17084+
perform_void_exec(con.get(), query);
1705717085
}
17058-
perform_void_exec(db, query);
1705917086
}
1706017087
};
1706117088
}
@@ -18069,9 +18096,6 @@ namespace sqlite_orm {
1806918096
void open_forever() {
1807018097
this->isOpenedForever = true;
1807118098
this->connection->retain();
18072-
if (1 == this->connection->retain_count()) {
18073-
this->on_open_internal(this->connection->get());
18074-
}
1807518099
}
1807618100

1807718101
/**
@@ -18384,7 +18408,7 @@ namespace sqlite_orm {
1838418408
}
1838518409

1838618410
backup_t make_backup_to(const std::string& filename) {
18387-
auto holder = std::make_unique<connection_holder>(filename);
18411+
auto holder = std::make_unique<connection_holder>(filename, true, nullptr);
1838818412
connection_ref conRef{*holder};
1838918413
return {conRef, "main", this->get_connection(), "main", std::move(holder)};
1839018414
}
@@ -18394,7 +18418,7 @@ namespace sqlite_orm {
1839418418
}
1839518419

1839618420
backup_t make_backup_from(const std::string& filename) {
18397-
auto holder = std::make_unique<connection_holder>(filename);
18421+
auto holder = std::make_unique<connection_holder>(filename, true, nullptr);
1839818422
connection_ref conRef{*holder};
1839918423
return {this->get_connection(), "main", conRef, "main", std::move(holder)};
1840018424
}
@@ -18442,22 +18466,25 @@ namespace sqlite_orm {
1844218466
pragma(std::bind(&storage_base::get_connection, this)),
1844318467
limit(std::bind(&storage_base::get_connection, this)),
1844418468
inMemory(filename.empty() || filename == ":memory:"),
18445-
connection(std::make_unique<connection_holder>(std::move(filename))),
18469+
connection(std::make_unique<connection_holder>(
18470+
std::move(filename),
18471+
inMemory,
18472+
std::bind(&storage_base::on_open_internal, this, std::placeholders::_1))),
1844618473
cachedForeignKeysCount(foreignKeysCount) {
1844718474
if (this->inMemory) {
1844818475
this->connection->retain();
18449-
this->on_open_internal(this->connection->get());
1845018476
}
1845118477
}
1845218478

1845318479
storage_base(const storage_base& other) :
1845418480
on_open(other.on_open), pragma(std::bind(&storage_base::get_connection, this)),
1845518481
limit(std::bind(&storage_base::get_connection, this)), inMemory(other.inMemory),
18456-
connection(std::make_unique<connection_holder>(other.connection->filename)),
18482+
connection(std::make_unique<connection_holder>(
18483+
*other.connection,
18484+
std::bind(&storage_base::on_open_internal, this, std::placeholders::_1))),
1845718485
cachedForeignKeysCount(other.cachedForeignKeysCount) {
1845818486
if (this->inMemory) {
1845918487
this->connection->retain();
18460-
this->on_open_internal(this->connection->get());
1846118488
}
1846218489
}
1846318490

@@ -18472,18 +18499,12 @@ namespace sqlite_orm {
1847218499

1847318500
void begin_transaction_internal(const std::string& query) {
1847418501
this->connection->retain();
18475-
if (1 == this->connection->retain_count()) {
18476-
this->on_open_internal(this->connection->get());
18477-
}
1847818502
sqlite3* db = this->connection->get();
1847918503
perform_void_exec(db, query);
1848018504
}
1848118505

1848218506
connection_ref get_connection() {
1848318507
connection_ref res{*this->connection};
18484-
if (1 == this->connection->retain_count()) {
18485-
this->on_open_internal(this->connection->get());
18486-
}
1848718508
return res;
1848818509
}
1848918510

@@ -18509,7 +18530,7 @@ namespace sqlite_orm {
1850918530
}
1851018531
#endif
1851118532
if (this->pragma.synchronous_ != -1) {
18512-
this->pragma.synchronous(this->pragma.synchronous_);
18533+
this->pragma.set_pragma("synchronous", this->pragma.synchronous_, db);
1851318534
}
1851418535

1851518536
if (this->pragma.journal_mode_ != -1) {

0 commit comments

Comments
 (0)