Skip to content

Commit 748d3d4

Browse files
committed
lib: diagnose RW commands inside RO transactions with location indicators
References: DESK-2595
1 parent 5ef184b commit 748d3d4

File tree

1 file changed

+21
-8
lines changed

1 file changed

+21
-8
lines changed

lib/dbhelper.cpp

Lines changed: 21 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,8 @@
1212

1313
namespace gromox {
1414

15+
static std::unordered_map<std::string, std::string> active_xa;
16+
static std::mutex active_xa_lock;
1517
unsigned int gx_sqlite_debug, gx_force_write_txn, gx_sql_deep_backtrace;
1618

1719
static bool write_statement(const char *q)
@@ -28,11 +30,18 @@ xstmt gx_sql_prep(sqlite3 *db, const char *query)
2830
if (gx_sqlite_debug >= 1)
2931
mlog(LV_DEBUG, "> sqlite3_prep(%s, %s)", znul(sqlite3_db_filename(db, nullptr)), query);
3032
auto state = sqlite3_txn_state(db, "main");
31-
if (state == SQLITE_TXN_READ && write_statement(query))
32-
mlog(LV_ERR, "> sqlite3_prep(%s) inside a readonly TXN", query);
33+
if (state == SQLITE_TXN_READ && write_statement(query)) {
34+
auto fn = sqlite3_db_filename(db, nullptr);
35+
if (fn == nullptr || *fn == '\0')
36+
fn = ":memory:";
37+
auto it = active_xa.find(fn);
38+
mlog(LV_ERR, "sqlite_prep(%s): ro held by [%s], rw at [%s]", query,
39+
it != active_xa.end() ? it->second.c_str() : "unknown",
40+
simple_backtrace().c_str());
41+
}
3342
int ret = sqlite3_prepare_v2(db, query, -1, &out.m_ptr, nullptr);
3443
if (ret != SQLITE_OK)
35-
mlog(LV_ERR, "sqlite3_prepare_v2(%s) \"%s\": %s (%d)",
44+
mlog(LV_ERR, "sqlite_prep(%s) \"%s\": %s (%d)",
3645
znul(sqlite3_db_filename(db, nullptr)),
3746
query, sqlite3_errstr(ret), ret);
3847
return out;
@@ -46,9 +55,6 @@ xtransaction &xtransaction::operator=(xtransaction &&o) noexcept
4655
return *this;
4756
}
4857

49-
static std::unordered_map<std::string, std::string> active_xa;
50-
static std::mutex active_xa_lock;
51-
5258
xtransaction::~xtransaction()
5359
{
5460
teardown();
@@ -176,8 +182,15 @@ int gx_sql_exec(sqlite3 *db, const char *query, unsigned int flags)
176182
if (gx_sqlite_debug >= 1)
177183
mlog(LV_DEBUG, "> sqlite3_exec(%s, %s)", znul(sqlite3_db_filename(db, nullptr)), query);
178184
auto state = sqlite3_txn_state(db, "main");
179-
if (state == SQLITE_TXN_READ && write_statement(query))
180-
mlog(LV_ERR, "> sqlite3_exec(%s) inside a readonly TXN", query);
185+
if (state == SQLITE_TXN_READ && write_statement(query)) {
186+
auto fn = sqlite3_db_filename(db, nullptr);
187+
if (fn == nullptr || *fn == '\0')
188+
fn = ":memory:";
189+
auto it = active_xa.find(fn);
190+
mlog(LV_ERR, "sqlite_exec(%s): ro held by [%s], rw at [%s]", query,
191+
it != active_xa.end() ? it->second.c_str() : "unknown",
192+
simple_backtrace().c_str());
193+
}
181194
auto ret = sqlite3_exec(db, query, nullptr, nullptr, &estr);
182195
if (ret == SQLITE_OK)
183196
return ret;

0 commit comments

Comments
 (0)