From c264d743ac61050c92795454c065fd9f74cbfc51 Mon Sep 17 00:00:00 2001 From: Julia Schroeder Date: Fri, 26 Apr 2024 17:09:26 +0200 Subject: [PATCH] exmdb: only lock giant_lock when necessary Switch from indiscriminately acquiring exclusive lock on db_base::giant_lock and lock it in shared or exclusive mode as required. --- exch/exmdb/db_engine.cpp | 44 +++++++++------------------- exch/exmdb/db_engine.h | 5 ++-- exch/exmdb/folder.cpp | 36 +++++++++++++---------- exch/exmdb/instance.cpp | 63 ++++++++++++++++++++-------------------- exch/exmdb/message.cpp | 38 ++++++++++++++---------- exch/exmdb/store.cpp | 6 ++-- exch/exmdb/store2.cpp | 8 ++--- exch/exmdb/table.cpp | 36 +++++++++++++---------- 8 files changed, 118 insertions(+), 118 deletions(-) diff --git a/exch/exmdb/db_engine.cpp b/exch/exmdb/db_engine.cpp index 4b2b99c15..bae7f1fd9 100644 --- a/exch/exmdb/db_engine.cpp +++ b/exch/exmdb/db_engine.cpp @@ -441,8 +441,7 @@ void db_base::handle_spares(sqlite3 *main, sqlite3 *eph) } db_conn::db_conn(db_base &base) : - m_base(&base), - m_lock(base.giant_lock, std::defer_lock) // will be acquired during open() + m_base(&base) { ++base.reference; } @@ -450,8 +449,7 @@ db_conn::db_conn(db_base &base) : db_conn::db_conn(db_conn &&o) : psqlite(std::move(o.psqlite)), m_sqlite_eph(std::move(o.m_sqlite_eph)), - m_base(std::move(o.m_base)), - m_lock(std::move(o.m_lock)) + m_base(std::move(o.m_base)) { o.psqlite = o.m_sqlite_eph = nullptr; o.m_base = nullptr; @@ -485,7 +483,6 @@ db_conn &db_conn::operator=(db_conn &&o) bool db_conn::open(const char *dir) try { m_base->get_dbs(dir, psqlite, m_sqlite_eph); - m_lock.lock(); return psqlite && m_sqlite_eph; } catch (const std::bad_alloc &) { mlog(LV_ERR, "E-1349: ENOMEM"); @@ -568,20 +565,9 @@ static void *db_expiry_thread(void *param) return nullptr; } -static bool db_reload(db_conn_ptr &pdb, const char *dir) -{ - pdb.reset(); - exmdb_server::free_env(); - if (g_exmdb_search_yield) - std::this_thread::yield(); /* +2 to +3% walltime */ - exmdb_server::build_env(EM_PRIVATE, dir); - pdb = db_engine_get_db(dir); - return !!pdb; -} - static BOOL db_engine_search_folder(const char *dir, cpid_t cpid, uint64_t search_fid, uint64_t scope_fid, const RESTRICTION *prestriction, - db_conn_ptr &pdb, db_base &dbase) + db_conn_ptr &pdb) { char sql_string[128]; auto sql_transact = gx_sql_begin_trans(pdb->psqlite, false); // ends before writes take place @@ -627,15 +613,7 @@ static BOOL db_engine_search_folder(const char *dir, cpid_t cpid, for (size_t i = 0, count = 0; i < pmessage_ids->count; ++i, ++count) { if (g_notify_stop) break; - auto t_msg = tp_now(); - if (count >= g_exmdb_search_pacing || - (t_msg - t_start) >= std::chrono::nanoseconds(g_exmdb_search_pacing_time)) { - if (!db_reload(pdb, dir)) - return false; - count = 0; - t_start = tp_now(); - } - auto sql_transact1 = gx_sql_begin_trans(pdb->psqlite, false); + auto sql_transact1 = gx_sql_begin_trans(pdb->psqlite, false); // ends before writes take place if (!sql_transact1) return false; if (!cu_eval_msg_restriction(pdb->psqlite, @@ -658,12 +636,14 @@ static BOOL db_engine_search_folder(const char *dir, cpid_t cpid, * have a search folder have a scope containing another search * folder; exmdb_provider only does a descendant check). */ + auto dbase = pdb->lock_base_wr(); pdb->proc_dynamic_event(cpid, dynamic_event::new_msg, - search_fid, pmessage_ids->pids[i], 0, dbase); + search_fid, pmessage_ids->pids[i], 0, *dbase); /* * Regular notifications */ - pdb->notify_link_creation(search_fid, pmessage_ids->pids[i], dbase); + pdb->notify_link_creation(search_fid, pmessage_ids->pids[i], *dbase); + dbase.reset(); if (sql_transact1.commit() != SQLITE_OK) return false; } @@ -822,17 +802,17 @@ static void *sf_popul_thread(void *param) auto pdb = db_engine_get_db(psearch->dir.c_str()); if (!pdb) goto NEXT_SEARCH; - db_base *dbase = pdb->m_base; for (size_t i = 0; i < pfolder_ids->count; ++i) { if (g_notify_stop) break; if (!db_engine_search_folder(psearch->dir.c_str(), psearch->cpid, psearch->folder_id, - pfolder_ids->pids[i], psearch->prestriction, pdb, *dbase)) + pfolder_ids->pids[i], psearch->prestriction, pdb)) break; } if (g_notify_stop) break; + auto dbase = pdb->lock_base_wr(); /* Stop animation (does nothing else in OL really) */ dbeng_notify_search_completion(*dbase, psearch->folder_id); pdb->notify_folder_modification(common_util_get_folder_parent_fid( @@ -850,6 +830,7 @@ static void *sf_popul_thread(void *param) if (t.type == table_type::content && psearch->folder_id == t.folder_id) table_ids.push_back(t.table_id); + dbase.reset(); pdb.reset(); /* * reload_ct triggers a table_change notification, and the @@ -3957,7 +3938,7 @@ void db_conn::begin_batch_mode(db_base &dbase) dbase.tables.b_batch = true; } -void db_conn::commit_batch_mode_release(db_conn_ptr &&pdb, db_base *dbase) +void db_conn::commit_batch_mode_release(db_conn_ptr &&pdb, db_base_wr_ptr &&dbase) { auto table_num = dbase->tables.table_list.size(); auto ptable_ids = table_num > 0 ? cu_alloc(table_num) : nullptr; @@ -3972,6 +3953,7 @@ void db_conn::commit_batch_mode_release(db_conn_ptr &&pdb, db_base *dbase) } } dbase->tables.b_batch = false; + dbase.reset(); pdb.reset(); auto dir = exmdb_server::get_dir(); while (table_num-- > 0) diff --git a/exch/exmdb/db_engine.h b/exch/exmdb/db_engine.h index 28ad854d2..8b7352e96 100644 --- a/exch/exmdb/db_engine.h +++ b/exch/exmdb/db_engine.h @@ -189,7 +189,7 @@ struct db_conn { void transport_new_mail(uint64_t folder_id, uint64_t msg_id, uint32_t msg_flags, const char *klass, const db_base &); void begin_batch_mode(db_base &); /* pdb will also be put */ - static void commit_batch_mode_release(std::optional &&pdb, db_base *); + static void commit_batch_mode_release(std::optional &&pdb, db_base_wr_ptr &&base); void cancel_batch_mode(db_base &); std::unique_ptr begin_optim(); @@ -200,8 +200,9 @@ struct db_conn { inline uint32_t next_table_id() { return ++m_base->tables.last_id; } sqlite3 *psqlite = nullptr, *m_sqlite_eph = nullptr; + + private: db_base *m_base = nullptr; - std::unique_lock m_lock; }; using db_conn_ptr = std::optional; diff --git a/exch/exmdb/folder.cpp b/exch/exmdb/folder.cpp index d1b996a6c..8759d3527 100644 --- a/exch/exmdb/folder.cpp +++ b/exch/exmdb/folder.cpp @@ -459,7 +459,7 @@ BOOL exmdb_server::create_folder(const char *dir, cpid_t cpid, PR_HIER_REV, &nt_time, &b_result); cu_set_property(MAPI_FOLDER, folder_id, CP_ACP, pdb->psqlite, PR_HIER_REV, &nt_time, &b_result); - pdb->notify_folder_creation(parent_id, folder_id, *pdb->m_base); + pdb->notify_folder_creation(parent_id, folder_id, *pdb->lock_base_rd()); if (sql_transact.commit() != 0) return false; *pfolder_id = rop_util_make_eid_ex(1, folder_id); @@ -543,7 +543,7 @@ BOOL exmdb_server::set_folder_properties(const char *dir, cpid_t cpid, fid_val, cpid, pdb->psqlite, pproperties, pproblems)) return FALSE; pdb->notify_folder_modification(common_util_get_folder_parent_fid( - pdb->psqlite, fid_val), fid_val, *pdb->m_base); + pdb->psqlite, fid_val), fid_val, *pdb->lock_base_rd()); if (sql_transact.commit() != 0) return false; return TRUE; @@ -563,7 +563,7 @@ BOOL exmdb_server::remove_folder_properties(const char *dir, fid_val, pdb->psqlite, pproptags)) return FALSE; pdb->notify_folder_modification(common_util_get_folder_parent_fid( - pdb->psqlite, fid_val), fid_val, *pdb->m_base); + pdb->psqlite, fid_val), fid_val, *pdb->lock_base_rd()); if (sql_transact.commit() != 0) return false; return TRUE; @@ -842,7 +842,7 @@ BOOL exmdb_server::delete_folder(const char *dir, cpid_t cpid, *pb_result = FALSE; return TRUE; } - db_base *dbase = pdb->m_base; + auto dbase = pdb->lock_base_wr(); if (!b_search) { snprintf(sql_string, std::size(sql_string), "SELECT count(*) FROM " "folders WHERE parent_id=%llu", LLU{fid_val}); @@ -874,7 +874,7 @@ BOOL exmdb_server::delete_folder(const char *dir, cpid_t cpid, pdb->proc_dynamic_event(cpid, dynamic_event::del_msg, fid_val, pstmt.col_int64(0), 0, *dbase); pstmt.finalize(); - pdb->delete_dynamic(fid_val, dbase); + pdb->delete_dynamic(fid_val, dbase.get()); } auto parent_id = common_util_get_folder_parent_fid(pdb->psqlite, fid_val); if (b_search) { @@ -892,7 +892,7 @@ BOOL exmdb_server::delete_folder(const char *dir, cpid_t cpid, if (!folder_empty_folder(pdb, cpid, nullptr, fid_val, DELETE_HARD_DELETE | DEL_MESSAGES | DEL_ASSOCIATED | DEL_FOLDERS, &b_partial, &normal_size, &fai_size, - nullptr, nullptr, dbase) || b_partial || + nullptr, nullptr, dbase.get()) || b_partial || !cu_adjust_store_size(pdb->psqlite, ADJ_DECREASE, normal_size, fai_size)) return FALSE; snprintf(sql_string, std::size(sql_string), "DELETE FROM folders" @@ -938,6 +938,7 @@ BOOL exmdb_server::delete_folder(const char *dir, cpid_t cpid, if (pdb->exec(sql_string) != SQLITE_OK) return FALSE; pdb->notify_folder_deletion(parent_id, fid_val, *dbase); + dbase.reset(); snprintf(sql_string, std::size(sql_string), "UPDATE folder_properties SET" " propval=propval+1 WHERE folder_id=%llu AND " "proptag=%u", LLU{parent_id}, PR_DELETED_FOLDER_COUNT); @@ -991,11 +992,12 @@ BOOL exmdb_server::empty_folder(const char *dir, cpid_t cpid, auto sql_transact = gx_sql_begin_trans(pdb->psqlite); if (!sql_transact) return false; - auto dbase = pdb->m_base; + auto dbase = pdb->lock_base_wr(); if (!folder_empty_folder(pdb, cpid, username, fid_val, flags, pb_partial, &normal_size, &fai_size, - &message_count, &folder_count, dbase)) + &message_count, &folder_count, dbase.get())) return FALSE; + dbase.reset(); if (message_count > 0) { snprintf(sql_string, std::size(sql_string), "UPDATE folder_properties SET " "propval=propval+%u WHERE folder_id=%llu AND " @@ -1520,11 +1522,12 @@ BOOL exmdb_server::copy_folder_internal(const char *dir, uint32_t folder_count = 0; uint64_t normal_size = 0, fai_size = 0; BOOL b_partial = false; - auto dbase = pdb->m_base; + auto dbase = pdb->lock_base_wr(); if (!folder_copy_folder_internal(pdb, account_id, cpid, b_guest, username, src_val, b_normal, b_fai, b_sub, dst_val, - &b_partial, &normal_size, &fai_size, &folder_count, dbase)) + &b_partial, &normal_size, &fai_size, &folder_count, dbase.get())) return FALSE; + dbase.reset(); if (folder_count > 0) { snprintf(sql_string, std::size(sql_string), "UPDATE folder_properties SET " "propval=propval+1 WHERE folder_id=%llu AND " @@ -1614,7 +1617,7 @@ BOOL exmdb_server::movecopy_folder(const char *dir, int account_id, cpid_t cpid, return TRUE; } } - auto dbase = pdb->m_base; + auto dbase = pdb->lock_base_wr(); if (!b_copy) { snprintf(sql_string, std::size(sql_string), "UPDATE folders SET parent_id=%llu" " WHERE folder_id=%llu", LLU{dst_val}, LLU{src_val}); @@ -1659,7 +1662,7 @@ BOOL exmdb_server::movecopy_folder(const char *dir, int account_id, cpid_t cpid, return FALSE; if (folder_type == FOLDER_SEARCH) { if (!folder_copy_search_folder(pdb, cpid, - b_guest, username, src_val, dst_val, &fid_val, dbase)) + b_guest, username, src_val, dst_val, &fid_val, dbase.get())) return FALSE; } else { if (!folder_copy_generic_folder(pdb->psqlite, @@ -1681,7 +1684,7 @@ BOOL exmdb_server::movecopy_folder(const char *dir, int account_id, cpid_t cpid, BOOL b_partial = false; if (!folder_copy_folder_internal(pdb, account_id, cpid, b_guest, username, src_val, TRUE, TRUE, TRUE, - fid_val, &b_partial, &normal_size, &fai_size, nullptr, dbase)) + fid_val, &b_partial, &normal_size, &fai_size, nullptr, dbase.get())) return FALSE; if (!cu_adjust_store_size(pdb->psqlite, ADJ_INCREASE, normal_size, fai_size)) @@ -1705,6 +1708,7 @@ BOOL exmdb_server::movecopy_folder(const char *dir, int account_id, cpid_t cpid, if (pdb->exec(sql_string) != SQLITE_OK) return FALSE; pdb->notify_folder_movecopy(b_copy, dst_val, fid_val, parent_val, src_val, *dbase); + dbase.reset(); if (sql_transact.commit() != 0) return false; *errcode = ecSuccess; @@ -1923,8 +1927,8 @@ BOOL exmdb_server::set_search_criteria(const char *dir, cpid_t cpid, } BOOL b_recursive = (search_flags & RECURSIVE_SEARCH) ? TRUE : false; BOOL b_update = false, b_populate = false; - auto dbase = pdb->m_base; - if (!folder_clear_search_folder(pdb, cpid, fid_val, dbase)) + auto dbase = pdb->lock_base_wr(); + if (!folder_clear_search_folder(pdb, cpid, fid_val, dbase.get())) return false; if (search_flags & RESTART_SEARCH) { b_populate = TRUE; @@ -1935,7 +1939,7 @@ BOOL exmdb_server::set_search_criteria(const char *dir, cpid_t cpid, pdb->update_dynamic(fid_val, search_flags, prestriction, &folder_ids, *dbase); else - pdb->delete_dynamic(fid_val, dbase); + pdb->delete_dynamic(fid_val, dbase.get()); if (sql_transact.commit() != 0) return false; diff --git a/exch/exmdb/instance.cpp b/exch/exmdb/instance.cpp index 89af475c3..7ed4ae751 100644 --- a/exch/exmdb/instance.cpp +++ b/exch/exmdb/instance.cpp @@ -324,7 +324,7 @@ BOOL exmdb_server::load_message_instance(const char *dir, const char *username, auto pdb = db_engine_get_db(dir); if (!pdb) return FALSE; - auto dbase = pdb->m_base; + auto dbase = pdb->lock_base_wr(); auto instance_id = dbase->next_instance_id(); if (instance_id == UINT32_MAX) return false; @@ -398,7 +398,7 @@ BOOL exmdb_server::load_embedded_instance(const char *dir, BOOL b_new, if (!pdb) return FALSE; auto sql_transact = gx_sql_begin_trans(pdb->psqlite); // may be required later but must be started here to avoid deadlocks - auto dbase = pdb->m_base; + auto dbase = pdb->lock_base_wr(); auto instance_id = dbase->next_instance_id(); if (instance_id == UINT32_MAX) return false; @@ -478,7 +478,7 @@ BOOL exmdb_server::get_embedded_cn(const char *dir, uint32_t instance_id, if (!pdb) return FALSE; /* No database access, so no transaction. */ - const db_base *dbase = pdb->m_base; + auto dbase = pdb->lock_base_rd(); auto pinstance = dbase->get_instance_c(instance_id); if (pinstance == nullptr || pinstance->type != instance_type::message) return FALSE; @@ -502,7 +502,7 @@ BOOL exmdb_server::reload_message_instance(const char *dir, auto sql_transact = gx_sql_begin_trans(pdb->psqlite, false); if (!sql_transact) return false; - auto dbase = pdb->m_base; + auto dbase = pdb->lock_base_wr(); auto pinstance = dbase->get_instance(instance_id); if (pinstance == nullptr || pinstance->type != instance_type::message) return FALSE; @@ -559,7 +559,7 @@ BOOL exmdb_server::clear_message_instance(const char *dir, uint32_t instance_id) if (!pdb) return FALSE; /* No database access, so no transaction. */ - auto dbase = pdb->m_base; + auto dbase = pdb->lock_base_wr(); auto pinstance = dbase->get_instance(instance_id); if (pinstance == nullptr || pinstance->type != instance_type::message) return FALSE; @@ -937,7 +937,7 @@ BOOL exmdb_server::read_message_instance(const char *dir, return FALSE; /* No database access, so no transaction. */ memset(pmsgctnt, 0, sizeof(MESSAGE_CONTENT)); - const db_base *dbase = pdb->m_base; + auto dbase = pdb->lock_base_rd(); auto pinstance = dbase->get_instance_c(instance_id); if (pinstance == nullptr || pinstance->type != instance_type::message) return FALSE; @@ -991,7 +991,7 @@ BOOL exmdb_server::write_message_instance(const char *dir, if (!pdb) return FALSE; /* No database access, so no transaction. */ - auto dbase = pdb->m_base; + auto dbase = pdb->lock_base_wr(); auto pinstance = dbase->get_instance(instance_id); if (pinstance == nullptr || pinstance->type != instance_type::message) return FALSE; @@ -1123,7 +1123,7 @@ BOOL exmdb_server::load_attachment_instance(const char *dir, if (!pdb) return FALSE; /* No database access, so no transaction. */ - auto dbase = pdb->m_base; + auto dbase = pdb->lock_base_wr(); auto instance_id = dbase->next_instance_id(); if (instance_id == UINT32_MAX) return false; @@ -1176,7 +1176,7 @@ BOOL exmdb_server::create_attachment_instance(const char *dir, if (!pdb) return FALSE; /* No database access, so no transaction. */ - auto dbase = pdb->m_base; + auto dbase = pdb->lock_base_wr(); auto instance_id = dbase->next_instance_id(); if (instance_id == UINT32_MAX) return false; @@ -1224,7 +1224,7 @@ BOOL exmdb_server::read_attachment_instance(const char *dir, return FALSE; /* No database access, so no transaction. */ memset(pattctnt, 0, sizeof(ATTACHMENT_CONTENT)); - const db_base *dbase = pdb->m_base; + auto dbase = pdb->lock_base_rd(); auto pinstance = dbase->get_instance_c(instance_id); if (pinstance == nullptr || pinstance->type != instance_type::attachment) return FALSE; @@ -1242,7 +1242,7 @@ BOOL exmdb_server::write_attachment_instance(const char *dir, if (!pdb) return FALSE; /* No database access, so no transaction. */ - const db_base *dbase = pdb->m_base; + auto dbase = pdb->lock_base_wr(); auto pinstance = dbase->get_instance_c(instance_id); if (pinstance == nullptr || pinstance->type != instance_type::attachment) return FALSE; @@ -1313,7 +1313,7 @@ BOOL exmdb_server::delete_message_instance_attachment(const char *dir, if (!pdb) return FALSE; /* No database access, so no transaction. */ - const db_base *dbase = pdb->m_base; + auto dbase = pdb->lock_base_wr(); auto pinstance = dbase->get_instance_c(message_instance_id); if (pinstance == nullptr || pinstance->type != instance_type::message) return FALSE; @@ -1351,7 +1351,7 @@ BOOL exmdb_server::flush_instance(const char *dir, uint32_t instance_id, if (!pdb) return FALSE; /* No direct database access, so no transaction. */ - auto dbase = pdb->m_base; + auto dbase = pdb->lock_base_wr(); auto pinstance = dbase->get_instance(instance_id); if (pinstance == nullptr) return FALSE; @@ -1504,6 +1504,7 @@ BOOL exmdb_server::flush_instance(const char *dir, uint32_t instance_id, folder_id = rop_util_make_eid_ex(1, pinstance->folder_id); if (!exmdb_server::is_private()) exmdb_server::set_public_username(pinstance->username.c_str()); + dbase.reset(); pdb.reset(); g_inside_flush_instance = true; BOOL b_result = exmdb_server::write_message(dir, account, CP_ACP, @@ -1519,7 +1520,7 @@ BOOL exmdb_server::unload_instance(const char *dir, uint32_t instance_id) if (!pdb) return FALSE; /* No database access, so no transaction. */ - auto dbase = pdb->m_base; + auto dbase = pdb->lock_base_wr(); for (auto it = dbase->instance_list.begin(); it != dbase->instance_list.end(); ++it) { if (it->instance_id == instance_id) { dbase->instance_list.erase(it); @@ -1596,7 +1597,7 @@ BOOL exmdb_server::get_instance_all_proptags(const char *dir, if (!pdb) return FALSE; /* No database access, so no transaction. */ - const db_base *dbase = pdb->m_base; + auto dbase = pdb->lock_base_rd(); auto pinstance = dbase->get_instance_c(instance_id); if (pinstance == nullptr) return FALSE; @@ -1899,7 +1900,7 @@ BOOL exmdb_server::get_instance_properties(const char *dir, if (!pdb) return FALSE; /* No database access, so no transaction. */ - const db_base *dbase = pdb->m_base; + auto dbase = pdb->lock_base_rd(); auto pinstance = dbase->get_instance_c(instance_id); if (pinstance == nullptr) return FALSE; @@ -2438,7 +2439,7 @@ BOOL exmdb_server::set_instance_properties(const char *dir, if (!db) return false; /* No database access, so no transaction. */ - auto dbase = db->m_base; + auto dbase = db->lock_base_wr(); auto ins = dbase->get_instance(instance_id); if (ins == nullptr) return false; @@ -2542,7 +2543,7 @@ BOOL exmdb_server::remove_instance_properties(const char *dir, if (!pdb) return FALSE; /* No database access, so no transaction. */ - const db_base *dbase = pdb->m_base; + auto dbase = pdb->lock_base_wr(); auto pinstance = dbase->get_instance_c(instance_id); if (pinstance == nullptr) return FALSE; @@ -2563,7 +2564,7 @@ BOOL exmdb_server::is_descendant_instance(const char *dir, if (!pdb) return FALSE; /* No database access, so no transaction. */ - const db_base *dbase = pdb->m_base; + auto dbase = pdb->lock_base_rd(); auto pinstance = dbase->get_instance_c(dst_instance_id); while (NULL != pinstance && 0 != pinstance->parent_id) { if (pinstance->parent_id == src_instance_id) { @@ -2583,7 +2584,7 @@ BOOL exmdb_server::empty_message_instance_rcpts(const char *dir, if (!pdb) return FALSE; /* No database access, so no transaction. */ - const db_base *dbase = pdb->m_base; + auto dbase = pdb->lock_base_wr(); auto pinstance = dbase->get_instance_c(instance_id); if (pinstance == nullptr || pinstance->type != instance_type::message) return FALSE; @@ -2602,7 +2603,7 @@ BOOL exmdb_server::get_message_instance_rcpts_num(const char *dir, if (!pdb) return FALSE; /* No database access, so no transaction. */ - const db_base *dbase = pdb->m_base; + auto dbase = pdb->lock_base_rd(); auto pinstance = dbase->get_instance_c(instance_id); if (pinstance == nullptr || pinstance->type != instance_type::message) return FALSE; @@ -2619,7 +2620,7 @@ BOOL exmdb_server::get_message_instance_rcpts_all_proptags(const char *dir, if (!pdb) return FALSE; /* No database access, so no transaction. */ - const db_base *dbase = pdb->m_base; + auto dbase = pdb->lock_base_rd(); auto pinstance = dbase->get_instance_c(instance_id); if (pinstance == nullptr || pinstance->type != instance_type::message) return FALSE; @@ -2661,7 +2662,7 @@ BOOL exmdb_server::get_message_instance_rcpts(const char *dir, if (!pdb) return FALSE; /* No database access, so no transaction. */ - const db_base *dbase = pdb->m_base; + auto dbase = pdb->lock_base_rd(); auto pinstance = dbase->get_instance_c(instance_id); if (pinstance == nullptr || pinstance->type != instance_type::message) return FALSE; @@ -2729,7 +2730,7 @@ BOOL exmdb_server::update_message_instance_rcpts(const char *dir, if (!pdb) return FALSE; /* No database access, so no transaction. */ - const db_base *dbase = pdb->m_base; + auto dbase = pdb->lock_base_wr(); auto pinstance = dbase->get_instance_c(instance_id); if (pinstance == nullptr || pinstance->type != instance_type::message) return FALSE; @@ -2785,7 +2786,7 @@ BOOL exmdb_server::copy_instance_rcpts(const char *dir, BOOL b_force, if (!pdb) return FALSE; /* No database access, so no transaction. */ - const db_base *dbase = pdb->m_base; + auto dbase = pdb->lock_base_wr(); auto pinstance_src = dbase->get_instance_c(src_instance_id); if (pinstance_src == nullptr || pinstance_src->type != instance_type::message) return FALSE; @@ -2818,7 +2819,7 @@ BOOL exmdb_server::empty_message_instance_attachments(const char *dir, if (!pdb) return FALSE; /* No database access, so no transaction. */ - const db_base *dbase = pdb->m_base; + auto dbase = pdb->lock_base_wr(); auto pinstance = dbase->get_instance_c(instance_id); if (pinstance == nullptr || pinstance->type != instance_type::message) return FALSE; @@ -2837,7 +2838,7 @@ BOOL exmdb_server::get_message_instance_attachments_num(const char *dir, if (!pdb) return FALSE; /* No database access, so no transaction. */ - const db_base *dbase = pdb->m_base; + auto dbase = pdb->lock_base_rd(); auto pinstance = dbase->get_instance_c(instance_id); if (pinstance == nullptr || pinstance->type != instance_type::message) return FALSE; @@ -2854,7 +2855,7 @@ BOOL exmdb_server::get_message_instance_attachment_table_all_proptags(const char if (!pdb) return FALSE; /* No database access, so no transaction. */ - const db_base *dbase = pdb->m_base; + auto dbase = pdb->lock_base_rd(); auto pinstance = dbase->get_instance_c(instance_id); if (pinstance == nullptr || pinstance->type != instance_type::message) return FALSE; @@ -2896,7 +2897,7 @@ BOOL exmdb_server::copy_instance_attachments(const char *dir, BOOL b_force, if (!pdb) return FALSE; /* No database access, so no transaction. */ - const db_base *dbase = pdb->m_base; + auto dbase = pdb->lock_base_wr(); auto pinstance_src = dbase->get_instance_c(src_instance_id); if (pinstance_src == nullptr || pinstance_src->type != instance_type::message) return FALSE; @@ -2933,7 +2934,7 @@ BOOL exmdb_server::query_message_instance_attachment_table(const char *dir, if (!pdb) return FALSE; /* No database access, so no transaction. */ - const db_base *dbase = pdb->m_base; + auto dbase = pdb->lock_base_rd(); auto pinstance = dbase->get_instance_c(instance_id); if (pinstance == nullptr || pinstance->type != instance_type::message) return FALSE; @@ -3001,7 +3002,7 @@ BOOL exmdb_server::set_message_instance_conflict(const char *dir, if (!pdb) return FALSE; /* No database access, so no transaction. */ - const db_base *dbase = pdb->m_base; + auto dbase = pdb->lock_base_wr(); auto pinstance = dbase->get_instance_c(instance_id); if (pinstance == nullptr || pinstance->type != instance_type::message) return FALSE; diff --git a/exch/exmdb/message.cpp b/exch/exmdb/message.cpp index 334ce0157..59616597c 100644 --- a/exch/exmdb/message.cpp +++ b/exch/exmdb/message.cpp @@ -155,7 +155,7 @@ BOOL exmdb_server::movecopy_message(const char *dir, int32_t account_id, uint64_t parent_fid = sqlite3_column_int64(pstmt, 0); bool is_associated = sqlite3_column_int64(pstmt, 1); pstmt.finalize(); - auto dbase = pdb->m_base; + auto dbase = pdb->lock_base_wr(); if (b_move) pdb->proc_dynamic_event(cpid, dynamic_event::del_msg, parent_fid, mid_val, 0, *dbase); @@ -169,6 +169,7 @@ BOOL exmdb_server::movecopy_message(const char *dir, int32_t account_id, dynamic_event::new_msg, fid_val, dst_val, 0, *dbase); pdb->notify_message_movecopy(!b_move ? TRUE : false, fid_val, dst_val, parent_fid, mid_val, *dbase); + dbase.reset(); BOOL b_update = TRUE; if (b_move) { if (exmdb_server::is_private()) { @@ -285,7 +286,7 @@ BOOL exmdb_server::movecopy_messages(const char *dir, int32_t account_id, b_check = TRUE; } auto b_batch = pmessage_ids->count >= MIN_BATCH_MESSAGE_NUM; - auto dbase = pdb->m_base; + auto dbase = pdb->lock_base_wr(); if (b_batch) pdb->begin_batch_mode(*dbase); auto cl_0 = make_scope_exit([&]() { @@ -448,7 +449,7 @@ BOOL exmdb_server::movecopy_messages(const char *dir, int32_t account_id, return false; if (b_batch) { b_batch = false; - db_conn::commit_batch_mode_release(std::move(pdb), dbase); + db_conn::commit_batch_mode_release(std::move(pdb),std::move(dbase)); } return TRUE; } @@ -491,7 +492,7 @@ BOOL exmdb_server::delete_messages(const char *dir, int32_t account_id, b_check = (permission & (frightsOwner | frightsDeleteAny)) ? false : TRUE; } auto b_batch = pmessage_ids->count >= MIN_BATCH_MESSAGE_NUM; - auto dbase = pdb->m_base; + auto dbase = pdb->lock_base_wr(); if (b_batch) pdb->begin_batch_mode(*dbase); auto cl_0 = make_scope_exit([&]() { @@ -652,7 +653,7 @@ BOOL exmdb_server::delete_messages(const char *dir, int32_t account_id, return false; if (b_batch) { b_batch = false; - db_conn::commit_batch_mode_release(std::move(pdb), dbase); + db_conn::commit_batch_mode_release(std::move(pdb), std::move(dbase)); } return TRUE; } @@ -923,10 +924,11 @@ BOOL exmdb_server::set_message_properties(const char *dir, BOOL b_result = false; cu_set_property(MAPI_FOLDER, fid_val, CP_ACP, pdb->psqlite, PR_LOCAL_COMMIT_TIME_MAX, &nt_time, &b_result); - auto dbase = pdb->m_base; + auto dbase = pdb->lock_base_wr(); pdb->proc_dynamic_event(cpid, dynamic_event::modify_msg, fid_val, mid_val, 0, *dbase); pdb->notify_message_modification(fid_val, mid_val, *dbase); + dbase.reset(); if (sql_transact.commit() != 0) return false; return TRUE; @@ -952,12 +954,13 @@ BOOL exmdb_server::remove_message_properties(const char *dir, cpid_t cpid, BOOL b_result = false; cu_set_property(MAPI_FOLDER, fid_val, CP_ACP, pdb->psqlite, PR_LOCAL_COMMIT_TIME_MAX, &nt_time, &b_result); - if (sql_transact.commit() != 0) - return false; - auto dbase = pdb->m_base; + auto dbase = pdb->lock_base_wr(); pdb->notify_message_modification(fid_val, mid_val, *dbase); pdb->proc_dynamic_event(cpid, dynamic_event::modify_msg, fid_val, mid_val, 0, *dbase); + dbase.reset(); + if (sql_transact.commit() != 0) + return false; return TRUE; } @@ -1013,10 +1016,11 @@ BOOL exmdb_server::set_message_read_state(const char *dir, BOOL b_result = false; cu_set_property(MAPI_FOLDER, fid_val, CP_ACP, pdb->psqlite, PR_LOCAL_COMMIT_TIME_MAX, &nt_time, &b_result); - auto dbase = pdb->m_base; + auto dbase = pdb->lock_base_wr(); pdb->proc_dynamic_event(CP_ACP, dynamic_event::modify_msg, fid_val, mid_val, 0, *dbase); pdb->notify_message_modification(fid_val, mid_val, *dbase); + dbase.reset(); if (sql_transact.commit() != 0) return false; *pread_cn = rop_util_make_eid_ex(1, read_cn); @@ -1341,10 +1345,11 @@ BOOL exmdb_server::link_message(const char *dir, cpid_t cpid, " VALUES (%llu, %llu)", LLU{fid_val}, LLU{mid_val}); if (pdb->exec(sql_string) != SQLITE_OK) return FALSE; - auto dbase = pdb->m_base; + auto dbase = pdb->lock_base_wr(); pdb->proc_dynamic_event(cpid, dynamic_event::new_msg, fid_val, mid_val, 0, *dbase); pdb->notify_link_creation(fid_val, mid_val, *dbase); + dbase.reset(); if (sql_transact.commit() != SQLITE_OK) return FALSE; *pb_result = TRUE; @@ -1368,10 +1373,11 @@ BOOL exmdb_server::unlink_message(const char *dir, snprintf(sql_string, std::size(sql_string), "DELETE FROM search_result" " WHERE folder_id=%llu AND message_id=%llu", LLU{fid_val}, LLU{mid_val}); - auto dbase = pdb->m_base; + auto dbase = pdb->lock_base_wr(); pdb->proc_dynamic_event(cpid, dynamic_event::del_msg, fid_val, mid_val, 0, *dbase); pdb->notify_link_deletion(fid_val, mid_val, *dbase); + dbase.reset(); if (pdb->exec(sql_string) != SQLITE_OK) return FALSE; return TRUE; @@ -3749,7 +3755,7 @@ BOOL exmdb_server::deliver_message(const char *dir, const char *from_address, return FALSE; } if (dlflags & DELIVERY_DO_NOTIF) { - auto dbase = pdb->m_base; + auto dbase = pdb->lock_base_wr(); for (const auto &mn : seen.msg) { pdb->proc_dynamic_event(cpid, dynamic_event::new_msg, mn.folder_id, mn.message_id, 0, *dbase); @@ -3831,7 +3837,7 @@ BOOL exmdb_server::write_message_v2(const char *dir, const char *account, return false; } - auto dbase = pdb->m_base; + auto dbase = pdb->lock_base_wr(); if (b_exist) { pdb->proc_dynamic_event(cpid, dynamic_event::modify_msg, fid_val, mid_val, 0, *dbase); @@ -3841,6 +3847,7 @@ BOOL exmdb_server::write_message_v2(const char *dir, const char *account, dynamic_event::new_msg, fid_val, mid_val, 0, *dbase); pdb->notify_message_creation(fid_val, mid_val, *dbase); } + dbase.reset(); if (sql_transact.commit() != 0) return false; *pe_result = ecSuccess; @@ -3927,7 +3934,7 @@ BOOL exmdb_server::rule_new_message(const char *dir, const char *username, pdb->psqlite, fid_val, mid_val, std::move(digest)}, seen); if (ec != ecSuccess) return FALSE; - auto dbase = pdb->m_base; + auto dbase = pdb->lock_base_wr(); for (const auto &mn : seen.msg) { if (mid_val == mn.message_id) continue; @@ -3935,6 +3942,7 @@ BOOL exmdb_server::rule_new_message(const char *dir, const char *username, mn.folder_id, mn.message_id, 0, *dbase); pdb->notify_message_creation(mn.folder_id, mn.message_id, *dbase); } + dbase.reset(); if (sql_transact.commit() != 0) return false; return TRUE; diff --git a/exch/exmdb/store.cpp b/exch/exmdb/store.cpp index 47d1384ef..127d7ebe9 100644 --- a/exch/exmdb/store.cpp +++ b/exch/exmdb/store.cpp @@ -372,7 +372,7 @@ BOOL exmdb_server::subscribe_notification(const char *dir, if (!pdb) return FALSE; /* No database access, so no transaction. */ - auto dbase = pdb->m_base; + auto dbase = pdb->lock_base_wr(); uint32_t last_id = dbase->nsub_list.size() == 0 ? 0 : dbase->nsub_list.back().sub_id; nsub_node sub, *pnsub = ⊂ @@ -417,7 +417,7 @@ BOOL exmdb_server::unsubscribe_notification(const char *dir, uint32_t sub_id) if (!pdb) return FALSE; /* No database access, so no transaction. */ - auto dbase = pdb->m_base; + auto dbase = pdb->lock_base_wr(); auto i = std::find_if(dbase->nsub_list.begin(), dbase->nsub_list.end(), [&](const nsub_node &n) { return n.sub_id == sub_id; }); if (i != dbase->nsub_list.end()) @@ -433,7 +433,7 @@ BOOL exmdb_server::transport_new_mail(const char *dir, uint64_t folder_id, return FALSE; /* No database access, so no transaction. */ pdb->transport_new_mail(rop_util_get_gc_value(folder_id), - rop_util_get_gc_value(message_id), message_flags, pstr_class, *pdb->m_base); + rop_util_get_gc_value(message_id), message_flags, pstr_class, *pdb->lock_base_rd()); return TRUE; } diff --git a/exch/exmdb/store2.cpp b/exch/exmdb/store2.cpp index f75728452..994c6e103 100644 --- a/exch/exmdb/store2.cpp +++ b/exch/exmdb/store2.cpp @@ -56,7 +56,7 @@ BOOL exmdb_server::notify_new_mail(const char *dir, uint64_t folder_id, /* Notifications need an externally managed transaction on main. */ auto sql_trans = gx_sql_begin_trans(pdb->psqlite, false); pdb->notify_new_mail(rop_util_get_gc_value(folder_id), - rop_util_get_gc_value(message_id), *pdb->m_base); + rop_util_get_gc_value(message_id), *pdb->lock_base_wr()); return TRUE; } @@ -280,11 +280,11 @@ BOOL exmdb_server::purge_softdelete(const char *dir, const char *username, uint64_t normal_size = 0, fai_size = 0; uint32_t msg_count = 0, fld_count = 0; bool partial = false; - const db_base *dbase = db->m_base; + auto dbase = db->lock_base_wr(); if (!folder_purge_softdel(db, CP_ACP, username, fid_val, del_flags, - &partial, &normal_size, &fai_size, &msg_count, &fld_count, cutoff, dbase)) + &partial, &normal_size, &fai_size, &msg_count, &fld_count, cutoff, dbase.get())) return false; - + dbase.reset(); char qstr[116]; if (msg_count > 0) { snprintf(qstr, sizeof(qstr), "UPDATE folder_properties SET " diff --git a/exch/exmdb/table.cpp b/exch/exmdb/table.cpp index 9519858cb..1eb183103 100644 --- a/exch/exmdb/table.cpp +++ b/exch/exmdb/table.cpp @@ -274,7 +274,7 @@ BOOL exmdb_server::load_hierarchy_table(const char *dir, uint64_t folder_id, if (table_transact.commit() != 0) return false; *ptable_id = ptnode->table_id; - auto dbase = pdb->m_base; + auto dbase = pdb->lock_base_wr(); dbase->tables.table_list.splice(dbase->tables.table_list.end(), std::move(holder)); return TRUE; } catch (const std::bad_alloc &) { @@ -1018,8 +1018,9 @@ static BOOL table_load_content_table(db_conn_ptr &pdb, cpid_t cpid, cl_0.release(); if (table_transact.commit() != 0) return false; - auto dbase = pdb->m_base; + auto dbase = pdb->lock_base_wr(); dbase->tables.table_list.splice(dbase->tables.table_list.end(), std::move(holder)); + dbase.reset(); if (*ptable_id == 0) *ptable_id = table_id; *prow_count = 0; @@ -1071,7 +1072,7 @@ BOOL exmdb_server::reload_content_table(const char *dir, uint32_t table_id) auto pdb = db_engine_get_db(dir); if (!pdb) return FALSE; - auto dbase = pdb->m_base; + auto dbase = pdb->lock_base_wr(); auto &table_list = dbase->tables.table_list; auto iter = std::find_if(table_list.begin(), table_list.end(), [&](const table_node &t) { @@ -1189,7 +1190,7 @@ BOOL exmdb_server::load_permission_table(const char *dir, uint64_t folder_id, if (table_transact.commit() != 0) return false; *ptable_id = ptnode->table_id; - auto dbase = pdb->m_base; + auto dbase = pdb->lock_base_wr(); dbase->tables.table_list.splice(dbase->tables.table_list.end(), std::move(holder)); return TRUE; } catch (const std::bad_alloc &) { @@ -1365,7 +1366,7 @@ BOOL exmdb_server::load_rule_table(const char *dir, uint64_t folder_id, pstmt.finalize(); if (table_transact.commit() != 0) return false; - auto dbase = pdb->m_base; + auto dbase = pdb->lock_base_wr(); dbase->tables.table_list.splice(dbase->tables.table_list.end(), std::move(holder)); *ptable_id = ptnode->table_id; return TRUE; @@ -1380,7 +1381,7 @@ BOOL exmdb_server::unload_table(const char *dir, uint32_t table_id) if (!pdb) return FALSE; /* Only one SQL operation, no transaction needed. */ - auto dbase = pdb->m_base; + auto dbase = pdb->lock_base_wr(); auto &table_list = dbase->tables.table_list; auto iter = std::find_if(table_list.begin(), table_list.end(), [&](const table_node &t) { return t.table_id == table_id; }); @@ -1389,6 +1390,7 @@ BOOL exmdb_server::unload_table(const char *dir, uint32_t table_id) std::list holder; holder.splice(holder.end(), table_list, iter); + dbase.reset(); snprintf(sql_string, std::size(sql_string), "DROP TABLE t%u", table_id); if (pdb->eph_exec(sql_string) != SQLITE_OK) /* ignore - table_id is not going to get reused anyway */; @@ -1880,7 +1882,7 @@ BOOL exmdb_server::query_table(const char *dir, const char *username, /* Transaction is managed in query_* subfunctions. */ pset->count = 0; pset->pparray = NULL; - const db_base *dbase = pdb->m_base; + auto dbase = pdb->lock_base_rd(); auto ptnode = dbase->find_table(table_id); if (ptnode == nullptr) return TRUE; @@ -2300,7 +2302,7 @@ BOOL exmdb_server::match_table(const char *dir, const char *username, if (!pdb) return FALSE; /* Transaction is managed within match_tbl_* subfunctions. */ - const db_base *dbase = pdb->m_base; + auto dbase = pdb->lock_base_rd(); auto ptnode = dbase->find_table(table_id); if (ptnode == nullptr) { *pposition = -1; @@ -2334,7 +2336,7 @@ BOOL exmdb_server::locate_table(const char *dir, if (!pdb) return FALSE; /* Only one SQL operation, no transaction needed. */ - const db_base *dbase = pdb->m_base; + auto dbase = pdb->lock_base_rd(); auto ptnode = dbase->find_table(table_id); if (ptnode == nullptr) { *pposition = -1; @@ -2542,7 +2544,7 @@ BOOL exmdb_server::read_table_row(const char *dir, const char *username, if (!pdb) return FALSE; /* Transaction is managed within read_tblrow_* subfunction. */ - const db_base *dbase = pdb->m_base; + auto dbase = pdb->lock_base_rd(); auto ptnode = dbase->find_table(table_id); if (ptnode == nullptr) { ppropvals->count = 0; @@ -2572,7 +2574,7 @@ BOOL exmdb_server::mark_table(const char *dir, *pinst_id = 0; *pinst_num = 0; *prow_type = 0; - const db_base *dbase = pdb->m_base; + auto dbase = pdb->lock_base_rd(); auto ptnode = dbase->find_table(table_id); if (ptnode == nullptr) return TRUE; @@ -2628,10 +2630,11 @@ BOOL exmdb_server::get_table_all_proptags(const char *dir, auto pdb = db_engine_get_db(dir); if (!pdb) return FALSE; - const db_base *dbase = pdb->m_base; auto sql_transact = gx_sql_begin_trans(pdb->psqlite, false); if (!sql_transact) return false; + auto dbase = pdb->lock_base_rd(); + auto ptnode = dbase->find_table(table_id); if (ptnode == nullptr) { pproptags->count = 0; @@ -2830,7 +2833,7 @@ BOOL exmdb_server::expand_table(const char *dir, auto sql_transact_eph = gx_sql_begin_trans(pdb->m_sqlite_eph); if (!sql_transact_eph) return false; - const db_base *dbase = pdb->m_base; + auto dbase = pdb->lock_base_rd(); auto ptnode = dbase->find_table(table_id); if (ptnode == nullptr) { *pb_found = FALSE; @@ -2940,7 +2943,7 @@ BOOL exmdb_server::collapse_table(const char *dir, auto pdb = db_engine_get_db(dir); if (!pdb) return FALSE; - const db_base *dbase = pdb->m_base; + auto dbase = pdb->lock_base_rd(); auto ptnode = dbase->find_table(table_id); if (ptnode == nullptr) { *pb_found = FALSE; @@ -2990,6 +2993,7 @@ BOOL exmdb_server::collapse_table(const char *dir, return FALSE; snprintf(sql_string, std::size(sql_string), "UPDATE t%u SET" " idx=? WHERE row_id=?", ptnode->table_id); + dbase.reset(); auto pstmt1 = pdb->eph_prep(sql_string); if (pstmt1 == nullptr) return FALSE; @@ -3036,7 +3040,7 @@ BOOL exmdb_server::store_table_state(const char *dir, auto pdb = db_engine_get_db(dir); if (!pdb) return FALSE; - const db_base *dbase = pdb->m_base; + auto dbase = pdb->lock_base_rd(); auto ptnode = dbase->find_table(table_id); *pstate_id = 0; if (ptnode == nullptr) @@ -3323,7 +3327,7 @@ BOOL exmdb_server::restore_table_state(const char *dir, auto pdb = db_engine_get_db(dir); if (!pdb) return FALSE; - const db_base *dbase = pdb->m_base; + auto dbase = pdb->lock_base_rd(); auto ptnode = dbase->find_table(table_id); if (ptnode == nullptr) return TRUE;