diff --git a/exch/exmdb/db_engine.cpp b/exch/exmdb/db_engine.cpp index 70a062cd3..f485caaa2 100644 --- a/exch/exmdb/db_engine.cpp +++ b/exch/exmdb/db_engine.cpp @@ -566,6 +566,17 @@ static void *db_expiry_thread(void *param) return nullptr; } +void dg_notify(db_conn::NOTIFQ &¬ifq) +{ + for (auto &&[dg, idarr] : notifq) { + for (auto &&[remote_id, sub_ids] : idarr) { + dg.id_array = std::move(sub_ids); + notification_agent_backward_notify(remote_id, &dg); + } + } + notifq.clear(); +} + 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) @@ -639,13 +650,15 @@ 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). */ + db_conn::NOTIFQ notifq; 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, notifq); /* * Regular notifications */ - pdb->notify_link_creation(search_fid, pmessage_ids->pids[i], *dbase); + pdb->notify_link_creation(search_fid, pmessage_ids->pids[i], *dbase, notifq); + dg_notify(std::move(notifq)); dbase.reset(); } return TRUE; @@ -694,16 +707,8 @@ static db_conn::ID_ARRAYS db_engine_classify_id_array(const db_base &db, throw; } -static void dg_notify(DB_NOTIFY_DATAGRAM &&dg, db_conn::ID_ARRAYS &&a) -{ - for (auto &&[remote_id, sub_ids] : a) { - dg.id_array = std::move(sub_ids); - notification_agent_backward_notify(remote_id, &dg); - } -} - static void dbeng_notify_search_completion(const db_base &dbase, - uint64_t folder_id) try + uint64_t folder_id, db_conn::NOTIFQ ¬ifq) try { DB_NOTIFY_DATAGRAM datagram; auto dir = exmdb_server::get_dir(); @@ -718,7 +723,7 @@ static void dbeng_notify_search_completion(const db_base &dbase, return; datagram.db_notify.pdata = psearch_completed; psearch_completed->folder_id = folder_id; - dg_notify(std::move(datagram), std::move(parrays)); + notifq.emplace_back(std::move(datagram), std::move(parrays)); } catch (const std::bad_alloc &) { mlog(LV_ERR, "E-2118: ENOMEM"); } @@ -775,12 +780,14 @@ static void *sf_popul_thread(void *param) } if (g_notify_stop) break; + db_conn::NOTIFQ notifq; auto dbase = pdb->lock_base_wr(); /* Stop animation (does nothing else in OL really) */ - dbeng_notify_search_completion(*dbase, psearch->folder_id); + dbeng_notify_search_completion(*dbase, psearch->folder_id, notifq); pdb->notify_folder_modification(common_util_get_folder_parent_fid( pdb->psqlite, psearch->folder_id), - psearch->folder_id, *dbase); + psearch->folder_id, *dbase, notifq); + dg_notify(std::move(notifq)); std::vector table_ids; try { table_ids.reserve(dbase->tables.table_list.size()); @@ -955,7 +962,7 @@ void db_conn::delete_dynamic(uint64_t folder_id, db_base *dbase) static void dbeng_dynevt_1(db_conn *pdb, cpid_t cpid, uint64_t id1, uint64_t id2, uint64_t id3, uint32_t folder_type, - const dynamic_node *pdynamic, size_t i, db_base &dbase) + const dynamic_node *pdynamic, size_t i, db_base &dbase, db_conn::NOTIFQ ¬ifq) { BOOL b_exist, b_included, b_included1; uint64_t message_id; @@ -989,9 +996,9 @@ static void dbeng_dynevt_1(db_conn *pdb, cpid_t cpid, uint64_t id1, if (b_included != b_exist) return; if (b_included) { - pdb->notify_link_deletion(pdynamic->folder_id, message_id, dbase); + pdb->notify_link_deletion(pdynamic->folder_id, message_id, dbase, notifq); pdb->proc_dynamic_event(cpid, dynamic_event::del_msg, - pdynamic->folder_id, message_id, 0, dbase); + pdynamic->folder_id, message_id, 0, dbase, notifq); snprintf(sql_string, std::size(sql_string), "DELETE FROM search_result " "WHERE folder_id=%llu AND message_id=%llu", LLU{pdynamic->folder_id}, LLU{message_id}); @@ -1006,16 +1013,16 @@ static void dbeng_dynevt_1(db_conn *pdb, cpid_t cpid, uint64_t id1, "(folder_id, message_id) VALUES (%llu, %llu)", LLU{pdynamic->folder_id}, LLU{message_id}); if (pdb->exec(sql_string) == SQLITE_OK) { - pdb->notify_link_creation(pdynamic->folder_id, message_id, dbase); + pdb->notify_link_creation(pdynamic->folder_id, message_id, dbase, notifq); pdb->proc_dynamic_event(cpid, dynamic_event::new_msg, - pdynamic->folder_id, message_id, 0, dbase); + pdynamic->folder_id, message_id, 0, dbase, notifq); } } } static void dbeng_dynevt_2(db_conn *pdb, cpid_t cpid, dynamic_event event_type, uint64_t id1, uint64_t id2, const dynamic_node *pdynamic, size_t i, - db_base &dbase) + db_base &dbase, db_conn::NOTIFQ ¬ifq) { BOOL b_exist; BOOL b_included; @@ -1049,9 +1056,9 @@ static void dbeng_dynevt_2(db_conn *pdb, cpid_t cpid, dynamic_event event_type, "(folder_id, message_id) VALUES (%llu, %llu)", LLU{pdynamic->folder_id}, LLU{id2}); if (pdb->exec(sql_string) == SQLITE_OK) { - pdb->notify_link_creation(pdynamic->folder_id, id2, dbase); + pdb->notify_link_creation(pdynamic->folder_id, id2, dbase, notifq); pdb->proc_dynamic_event(cpid, dynamic_event::new_msg, - pdynamic->folder_id, id2, 0, dbase); + pdynamic->folder_id, id2, 0, dbase, notifq); } else { mlog(LV_DEBUG, "db_engine: failed to insert into search_result"); } @@ -1064,9 +1071,9 @@ static void dbeng_dynevt_2(db_conn *pdb, cpid_t cpid, dynamic_event event_type, } if (!b_exist) return; - pdb->notify_link_deletion(pdynamic->folder_id, id2, dbase); + pdb->notify_link_deletion(pdynamic->folder_id, id2, dbase, notifq); pdb->proc_dynamic_event(cpid, dynamic_event::del_msg, - pdynamic->folder_id, id2, 0, dbase); + pdynamic->folder_id, id2, 0, dbase, notifq); snprintf(sql_string, std::size(sql_string), "DELETE FROM search_result " "WHERE folder_id=%llu AND message_id=%llu", LLU{pdynamic->folder_id}, LLU{id2}); @@ -1087,25 +1094,25 @@ static void dbeng_dynevt_2(db_conn *pdb, cpid_t cpid, dynamic_event event_type, pdb->notify_folder_modification( common_util_get_folder_parent_fid( pdb->psqlite, pdynamic->folder_id), - pdynamic->folder_id, dbase); + pdynamic->folder_id, dbase, notifq); return; } snprintf(sql_string, std::size(sql_string), "INSERT INTO search_result " "(folder_id, message_id) VALUES (%llu, %llu)", LLU{pdynamic->folder_id}, LLU{id2}); if (pdb->exec(sql_string) == SQLITE_OK) { - pdb->notify_link_creation(pdynamic->folder_id, id2, dbase); + pdb->notify_link_creation(pdynamic->folder_id, id2, dbase, notifq); pdb->proc_dynamic_event(cpid, dynamic_event::new_msg, - pdynamic->folder_id, id2, 0, dbase); + pdynamic->folder_id, id2, 0, dbase, notifq); } else { mlog(LV_DEBUG, "db_engine: failed to insert into search_result"); } } else { if (!b_exist) return; - pdb->notify_link_deletion(pdynamic->folder_id, id2, dbase); + pdb->notify_link_deletion(pdynamic->folder_id, id2, dbase, notifq); pdb->proc_dynamic_event(cpid, dynamic_event::del_msg, - pdynamic->folder_id, id2, 0, dbase); + pdynamic->folder_id, id2, 0, dbase, notifq); snprintf(sql_string, std::size(sql_string), "DELETE FROM search_result " "WHERE folder_id=%llu AND message_id=%llu", LLU{pdynamic->folder_id}, LLU{id2}); @@ -1130,7 +1137,7 @@ static void dbeng_dynevt_2(db_conn *pdb, cpid_t cpid, dynamic_event event_type, * change). */ void db_conn::proc_dynamic_event(cpid_t cpid, dynamic_event event_type, - uint64_t id1, uint64_t id2, uint64_t id3, db_base &dbase) + uint64_t id1, uint64_t id2, uint64_t id3, db_base &dbase, NOTIFQ ¬ifq) { auto pdb = this; uint32_t folder_type; @@ -1152,10 +1159,12 @@ void db_conn::proc_dynamic_event(cpid_t cpid, dynamic_event event_type, */ for (size_t i = 0; i < pdynamic->folder_ids.count; ++i) { if (dynamic_event::move_folder == event_type) { - dbeng_dynevt_1(pdb, cpid, id1, id2, id3, folder_type, pdynamic, i, dbase); + dbeng_dynevt_1(pdb, cpid, id1, id2, id3, + folder_type, pdynamic, i, dbase, notifq); continue; } - dbeng_dynevt_2(pdb, cpid, event_type, id1, id2, pdynamic, i, dbase); + dbeng_dynevt_2(pdb, cpid, event_type, id1, id2, + pdynamic, i, dbase, notifq); } } } @@ -1998,7 +2007,8 @@ static void dbeng_notify_cttbl_add_row(db_conn *pdb, * because we access nsub_list. */ void db_conn::transport_new_mail(uint64_t folder_id, uint64_t message_id, - uint32_t message_flags, const char *pstr_class, const db_base &dbase) try + uint32_t message_flags, const char *pstr_class, const db_base &dbase, + NOTIFQ ¬ifq) try { DB_NOTIFY_DATAGRAM datagram; auto dir = exmdb_server::get_dir(); @@ -2016,13 +2026,13 @@ void db_conn::transport_new_mail(uint64_t folder_id, uint64_t message_id, pnew_mail->message_id = message_id; pnew_mail->message_flags = message_flags; pnew_mail->pmessage_class = pstr_class; - dg_notify(std::move(datagram), std::move(parrays)); + notifq.emplace_back(std::move(datagram), std::move(parrays)); } catch (const std::bad_alloc &) { mlog(LV_ERR, "E-2119: ENOMEM"); } void db_conn::notify_new_mail(uint64_t folder_id, uint64_t message_id, - db_base &dbase) try + db_base &dbase, NOTIFQ ¬ifq) try { auto pdb = this; void *pvalue; @@ -2047,17 +2057,17 @@ void db_conn::notify_new_mail(uint64_t folder_id, uint64_t message_id, pdb->psqlite, PR_MESSAGE_CLASS, &pvalue) || pvalue == nullptr) return; pnew_mail->pmessage_class = static_cast(pvalue); - dg_notify(std::move(datagram), std::move(parrays)); + notifq.emplace_back(std::move(datagram), std::move(parrays)); } dbeng_notify_cttbl_add_row(pdb, folder_id, message_id, dbase); pdb->notify_folder_modification(common_util_get_folder_parent_fid( - pdb->psqlite, folder_id), folder_id, dbase); + pdb->psqlite, folder_id), folder_id, dbase, notifq); } catch (const std::bad_alloc &) { mlog(LV_ERR, "E-2120: ENOMEM"); } void db_conn::notify_message_creation(uint64_t folder_id, - uint64_t message_id, db_base &dbase) try + uint64_t message_id, db_base &dbase, NOTIFQ ¬ifq) try { auto pdb = this; DB_NOTIFY_DATAGRAM datagram; @@ -2074,17 +2084,17 @@ void db_conn::notify_message_creation(uint64_t folder_id, pcreated_mail->folder_id = folder_id; pcreated_mail->message_id = message_id; pcreated_mail->proptags.count = 0; - dg_notify(std::move(datagram), std::move(parrays)); + notifq.emplace_back(std::move(datagram), std::move(parrays)); } dbeng_notify_cttbl_add_row(pdb, folder_id, message_id, dbase); pdb->notify_folder_modification(common_util_get_folder_parent_fid( - pdb->psqlite, folder_id), folder_id, dbase); + pdb->psqlite, folder_id), folder_id, dbase, notifq); } catch (const std::bad_alloc &) { mlog(LV_ERR, "E-2121: ENOMEM"); } void db_conn::notify_link_creation(uint64_t srch_fld, uint64_t message_id, - db_base &dbase) try + db_base &dbase, NOTIFQ ¬ifq) try { auto pdb = this; uint64_t anchor_fld; @@ -2107,11 +2117,11 @@ void db_conn::notify_link_creation(uint64_t srch_fld, uint64_t message_id, plinked_mail->message_id = message_id; plinked_mail->parent_id = srch_fld; plinked_mail->proptags.count = 0; - dg_notify(std::move(datagram), std::move(parrays)); + notifq.emplace_back(std::move(datagram), std::move(parrays)); } dbeng_notify_cttbl_add_row(pdb, srch_fld, message_id, dbase); pdb->notify_folder_modification(common_util_get_folder_parent_fid( - pdb->psqlite, srch_fld), srch_fld, dbase); + pdb->psqlite, srch_fld), srch_fld, dbase, notifq); } catch (const std::bad_alloc &) { mlog(LV_ERR, "E-2122: ENOMEM"); } @@ -2272,7 +2282,7 @@ static void dbeng_notify_hiertbl_add_row(db_conn *pdb, } void db_conn::notify_folder_creation(uint64_t parent_id, uint64_t folder_id, - const db_base &dbase) try + const db_base &dbase, NOTIFQ ¬ifq) try { auto pdb = this; DB_NOTIFY_DATAGRAM datagram; @@ -2289,11 +2299,11 @@ void db_conn::notify_folder_creation(uint64_t parent_id, uint64_t folder_id, pcreated_folder->folder_id = folder_id; pcreated_folder->parent_id = parent_id; pcreated_folder->proptags.count = 0; - dg_notify(std::move(datagram), std::move(parrays)); + notifq.emplace_back(std::move(datagram), std::move(parrays)); } dbeng_notify_hiertbl_add_row(pdb, parent_id, folder_id, dbase); pdb->notify_folder_modification(common_util_get_folder_parent_fid( - pdb->psqlite, parent_id), parent_id, dbase); + pdb->psqlite, parent_id), parent_id, dbase, notifq); } catch (const std::bad_alloc &) { mlog(LV_ERR, "E-2123: ENOMEM"); } @@ -2810,7 +2820,7 @@ static void dbeng_notify_cttbl_delete_row(db_conn *pdb, } void db_conn::notify_message_deletion(uint64_t folder_id, uint64_t message_id, - db_base &dbase) try + db_base &dbase, NOTIFQ ¬ifq) try { auto pdb = this; DB_NOTIFY_DATAGRAM datagram; @@ -2826,17 +2836,17 @@ void db_conn::notify_message_deletion(uint64_t folder_id, uint64_t message_id, datagram.db_notify.pdata = pdeleted_mail; pdeleted_mail->folder_id = folder_id; pdeleted_mail->message_id = message_id; - dg_notify(std::move(datagram), std::move(parrays)); + notifq.emplace_back(std::move(datagram), std::move(parrays)); } dbeng_notify_cttbl_delete_row(pdb, folder_id, message_id, dbase); pdb->notify_folder_modification(common_util_get_folder_parent_fid( - pdb->psqlite, folder_id), folder_id, dbase); + pdb->psqlite, folder_id), folder_id, dbase, notifq); } catch (const std::bad_alloc &) { mlog(LV_ERR, "E-2124: ENOMEM"); } void db_conn::notify_link_deletion(uint64_t parent_id, uint64_t message_id, - db_base &dbase) try + db_base &dbase, NOTIFQ ¬ifq) try { auto pdb = this; uint64_t folder_id; @@ -2859,11 +2869,11 @@ void db_conn::notify_link_deletion(uint64_t parent_id, uint64_t message_id, punlinked_mail->folder_id = folder_id; punlinked_mail->message_id = message_id; punlinked_mail->parent_id = parent_id; - dg_notify(std::move(datagram), std::move(parrays)); + notifq.emplace_back(std::move(datagram), std::move(parrays)); } dbeng_notify_cttbl_delete_row(pdb, parent_id, message_id, dbase); pdb->notify_folder_modification(common_util_get_folder_parent_fid( - pdb->psqlite, parent_id), parent_id, dbase); + pdb->psqlite, parent_id), parent_id, dbase, notifq); } catch (const std::bad_alloc &) { mlog(LV_ERR, "E-2125: ENOMEM"); } @@ -2943,7 +2953,7 @@ static void dbeng_notify_hiertbl_delete_row(db_conn *pdb, } void db_conn::notify_folder_deletion(uint64_t parent_id, uint64_t folder_id, - const db_base &dbase) try + const db_base &dbase, NOTIFQ ¬ifq) try { auto pdb = this; DB_NOTIFY_DATAGRAM datagram; @@ -2959,7 +2969,7 @@ void db_conn::notify_folder_deletion(uint64_t parent_id, uint64_t folder_id, datagram.db_notify.pdata = pdeleted_folder; pdeleted_folder->parent_id = parent_id; pdeleted_folder->folder_id = folder_id; - dg_notify(std::move(datagram), std::move(parrays)); + notifq.emplace_back(std::move(datagram), std::move(parrays)); } dbeng_notify_hiertbl_delete_row(pdb, parent_id, folder_id, dbase); } catch (const std::bad_alloc &) { @@ -3558,7 +3568,7 @@ static void dbeng_notify_cttbl_modify_row(db_conn *pdb, } void db_conn::notify_message_modification(uint64_t folder_id, uint64_t message_id, - db_base &dbase) try + db_base &dbase, NOTIFQ ¬ifq) try { auto pdb = this; DB_NOTIFY_DATAGRAM datagram; @@ -3575,11 +3585,11 @@ void db_conn::notify_message_modification(uint64_t folder_id, uint64_t message_i pmodified_mail->folder_id = folder_id; pmodified_mail->message_id = message_id; pmodified_mail->proptags.count = 0; - dg_notify(std::move(datagram), std::move(parrays)); + notifq.emplace_back(std::move(datagram), std::move(parrays)); } dbeng_notify_cttbl_modify_row(pdb, folder_id, message_id, dbase); pdb->notify_folder_modification(common_util_get_folder_parent_fid( - pdb->psqlite, folder_id), folder_id, dbase); + pdb->psqlite, folder_id), folder_id, dbase, notifq); } catch (const std::bad_alloc &) { mlog(LV_ERR, "E-2127: ENOMEM"); } @@ -3748,7 +3758,7 @@ static void dbeng_notify_hiertbl_modify_row(const db_conn *pdb, } void db_conn::notify_folder_modification(uint64_t parent_id, uint64_t folder_id, - const db_base &dbase) try + const db_base &dbase, NOTIFQ ¬ifq) try { auto pdb = this; DB_NOTIFY_DATAGRAM datagram; @@ -3767,7 +3777,7 @@ void db_conn::notify_folder_modification(uint64_t parent_id, uint64_t folder_id, pmodified_folder->ptotal = NULL; pmodified_folder->punread = NULL; pmodified_folder->proptags.count = 0; - dg_notify(std::move(datagram), std::move(parrays)); + notifq.emplace_back(std::move(datagram), std::move(parrays)); } dbeng_notify_hiertbl_modify_row(pdb, parent_id, folder_id, dbase); } catch (const std::bad_alloc &) { @@ -3776,7 +3786,7 @@ void db_conn::notify_folder_modification(uint64_t parent_id, uint64_t folder_id, void db_conn::notify_message_movecopy(BOOL b_copy, uint64_t folder_id, uint64_t message_id, uint64_t old_fid, uint64_t old_mid, - db_base &dbase) try + db_base &dbase, NOTIFQ ¬ifq) try { auto pdb = this; DB_NOTIFY_DATAGRAM datagram; @@ -3809,16 +3819,16 @@ void db_conn::notify_message_movecopy(BOOL b_copy, uint64_t folder_id, pmvcp_mail->message_id = message_id; pmvcp_mail->old_folder_id = old_fid; pmvcp_mail->old_message_id = old_mid; - dg_notify(std::move(datagram), std::move(recv_list)); + notifq.emplace_back(std::move(datagram), std::move(recv_list)); } if (!b_copy) { dbeng_notify_cttbl_delete_row(pdb, old_fid, old_mid, dbase); pdb->notify_folder_modification(common_util_get_folder_parent_fid( - pdb->psqlite, old_fid), old_fid, dbase); + pdb->psqlite, old_fid), old_fid, dbase, notifq); } dbeng_notify_cttbl_add_row(pdb, folder_id, message_id, dbase); pdb->notify_folder_modification(common_util_get_folder_parent_fid( - pdb->psqlite, folder_id), folder_id, dbase); + pdb->psqlite, folder_id), folder_id, dbase, notifq); } catch (const std::bad_alloc &) { mlog(LV_ERR, "E-1521: ENOMEM"); return; @@ -3826,7 +3836,7 @@ void db_conn::notify_message_movecopy(BOOL b_copy, uint64_t folder_id, void db_conn::notify_folder_movecopy(BOOL b_copy, uint64_t parent_id, uint64_t folder_id, uint64_t old_pid, uint64_t old_fid, - const db_base &dbase) try + const db_base &dbase, NOTIFQ ¬ifq) try { auto pdb = this; DB_NOTIFY_DATAGRAM datagram; @@ -3860,22 +3870,23 @@ void db_conn::notify_folder_movecopy(BOOL b_copy, uint64_t parent_id, pmvcp_folder->parent_id = parent_id; pmvcp_folder->old_folder_id = old_fid; pmvcp_folder->old_parent_id = old_pid; - dg_notify(std::move(datagram), std::move(recv_list)); + notifq.emplace_back(std::move(datagram), std::move(recv_list)); } if (!b_copy) { dbeng_notify_hiertbl_delete_row(pdb, old_pid, old_fid, dbase); pdb->notify_folder_modification(common_util_get_folder_parent_fid( - pdb->psqlite, old_pid), old_pid, dbase); + pdb->psqlite, old_pid), old_pid, dbase, notifq); } dbeng_notify_hiertbl_add_row(pdb, parent_id, folder_id, dbase); pdb->notify_folder_modification(common_util_get_folder_parent_fid( - pdb->psqlite, parent_id), parent_id, dbase); + pdb->psqlite, parent_id), parent_id, dbase, notifq); } catch (const std::bad_alloc &) { mlog(LV_ERR, "E-1522: ENOMEM"); return; } -void db_conn::notify_cttbl_reload(uint32_t table_id, const db_base &dbase) try +void db_conn::notify_cttbl_reload(uint32_t table_id, const db_base &dbase, + NOTIFQ ¬ifq) try { DB_NOTIFY_DATAGRAM datagram; const auto &list = dbase.tables.table_list; diff --git a/exch/exmdb/db_engine.hpp b/exch/exmdb/db_engine.hpp index d2005f140..054a53825 100644 --- a/exch/exmdb/db_engine.hpp +++ b/exch/exmdb/db_engine.hpp @@ -168,6 +168,8 @@ struct db_conn { } }; using ID_ARRAYS = std::map, xless>; + /* As long as any NOTIFQ object is alive, dbase should be held at least read-locked. */ + using NOTIFQ = std::vector>; db_conn(db_base &); ~db_conn(); @@ -179,20 +181,20 @@ struct db_conn { db_base_wr_ptr lock_base_wr(); void update_dynamic(uint64_t folder_id, uint32_t search_flags, const RESTRICTION *prestriction, const LONGLONG_ARRAY *pfolder_ids, db_base &); void delete_dynamic(uint64_t folder_id, db_base *); - void proc_dynamic_event(cpid_t, enum dynamic_event, uint64_t id1, uint64_t id2, uint64_t id3, db_base &); - void notify_new_mail(uint64_t folder_id, uint64_t msg_id, db_base &); - void notify_message_creation(uint64_t folder_id, uint64_t msg_id, db_base &); - void notify_link_creation(uint64_t parent_id, uint64_t msg_id, db_base &); - void notify_folder_creation(uint64_t parent_id, uint64_t folder_id, const db_base &); - void notify_message_deletion(uint64_t folder_id, uint64_t msg_id, db_base &); - void notify_link_deletion(uint64_t parent_id, uint64_t msg_id, db_base &); - void notify_folder_deletion(uint64_t parent_id, uint64_t folder_id, const db_base &); - void notify_message_modification(uint64_t folder_id, uint64_t msg_id, db_base &); - void notify_folder_modification(uint64_t parent_id, uint64_t folder_id, const db_base &); - void notify_message_movecopy(BOOL b_copy, uint64_t folder_id, uint64_t msg_id, uint64_t old_fid, uint64_t old_mid, db_base &); - void notify_folder_movecopy(BOOL b_copy, uint64_t parent_id, uint64_t folder_id, uint64_t old_pid, uint64_t old_fid, const db_base &); - void notify_cttbl_reload(uint32_t table_id, const db_base &); - void transport_new_mail(uint64_t folder_id, uint64_t msg_id, uint32_t msg_flags, const char *klass, const db_base &); + void proc_dynamic_event(cpid_t, enum dynamic_event, uint64_t id1, uint64_t id2, uint64_t id3, db_base &, NOTIFQ &); + void notify_new_mail(uint64_t folder_id, uint64_t msg_id, db_base &, NOTIFQ &); + void notify_message_creation(uint64_t folder_id, uint64_t msg_id, db_base &, NOTIFQ &); + void notify_link_creation(uint64_t parent_id, uint64_t msg_id, db_base &, NOTIFQ &); + void notify_folder_creation(uint64_t parent_id, uint64_t folder_id, const db_base &, NOTIFQ &); + void notify_message_deletion(uint64_t folder_id, uint64_t msg_id, db_base &, NOTIFQ &); + void notify_link_deletion(uint64_t parent_id, uint64_t msg_id, db_base &, NOTIFQ &); + void notify_folder_deletion(uint64_t parent_id, uint64_t folder_id, const db_base &, NOTIFQ &); + void notify_message_modification(uint64_t folder_id, uint64_t msg_id, db_base &, NOTIFQ &); + void notify_folder_modification(uint64_t parent_id, uint64_t folder_id, const db_base &, NOTIFQ &); + void notify_message_movecopy(BOOL b_copy, uint64_t folder_id, uint64_t msg_id, uint64_t old_fid, uint64_t old_mid, db_base &, NOTIFQ &); + void notify_folder_movecopy(BOOL b_copy, uint64_t parent_id, uint64_t folder_id, uint64_t old_pid, uint64_t old_fid, const db_base &, NOTIFQ &); + void notify_cttbl_reload(uint32_t table_id, const db_base &, NOTIFQ &); + void transport_new_mail(uint64_t folder_id, uint64_t msg_id, uint32_t msg_flags, const char *klass, const db_base &, NOTIFQ &); void begin_batch_mode(db_base &); /* pdb will also be put */ static void commit_batch_mode_release(std::optional &&pdb, db_base_wr_ptr &&base); @@ -221,6 +223,7 @@ extern BOOL db_engine_vacuum(const char *path); BOOL db_engine_unload_db(const char *path); extern BOOL db_engine_enqueue_populating_criteria(const char *dir, cpid_t, uint64_t folder_id, BOOL recursive, const RESTRICTION *, const LONGLONG_ARRAY *folder_ids); extern bool db_engine_check_populating(const char *dir, uint64_t folder_id); +extern void dg_notify(db_conn::NOTIFQ &&); extern unsigned int g_exmdb_schema_upgrades, g_exmdb_search_pacing; extern unsigned long long g_exmdb_search_pacing_time, g_exmdb_lock_timeout; diff --git a/exch/exmdb/folder.cpp b/exch/exmdb/folder.cpp index 1ef9a7e3b..bb4932c10 100644 --- a/exch/exmdb/folder.cpp +++ b/exch/exmdb/folder.cpp @@ -456,9 +456,13 @@ 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->lock_base_rd()); + + db_conn::NOTIFQ notifq; + auto dbase = pdb->lock_base_rd(); + pdb->notify_folder_creation(parent_id, folder_id, *dbase, notifq); if (sql_transact.commit() != SQLITE_OK) return false; + dg_notify(std::move(notifq)); *pfolder_id = rop_util_make_eid_ex(1, folder_id); *errcode = ecSuccess; return TRUE; @@ -539,10 +543,14 @@ BOOL exmdb_server::set_folder_properties(const char *dir, cpid_t cpid, if (!cu_set_properties(MAPI_FOLDER, fid_val, cpid, pdb->psqlite, pproperties, pproblems)) return FALSE; + + db_conn::NOTIFQ notifq; + auto dbase = pdb->lock_base_rd(); pdb->notify_folder_modification(common_util_get_folder_parent_fid( - pdb->psqlite, fid_val), fid_val, *pdb->lock_base_rd()); + pdb->psqlite, fid_val), fid_val, *dbase, notifq); if (sql_transact.commit() != SQLITE_OK) return false; + dg_notify(std::move(notifq)); return TRUE; } @@ -559,10 +567,14 @@ BOOL exmdb_server::remove_folder_properties(const char *dir, if (!cu_remove_properties(MAPI_FOLDER, fid_val, pdb->psqlite, pproptags)) return FALSE; + + db_conn::NOTIFQ notifq; + auto dbase = pdb->lock_base_rd(); pdb->notify_folder_modification(common_util_get_folder_parent_fid( - pdb->psqlite, fid_val), fid_val, *pdb->lock_base_rd()); + pdb->psqlite, fid_val), fid_val, *dbase, notifq); if (sql_transact.commit() != SQLITE_OK) return false; + dg_notify(std::move(notifq)); return TRUE; } @@ -586,7 +598,7 @@ BOOL exmdb_server::remove_folder_properties(const char *dir, static BOOL folder_empty_sf(db_conn_ptr &pdb, cpid_t cpid, const char *username, uint64_t folder_id, unsigned int del_flags, BOOL *pb_partial, uint64_t *pnormal_size, uint64_t *pfai_size, uint32_t *pmessage_count, - uint32_t *pfolder_count, db_base *dbase) + uint32_t *pfolder_count, db_base *dbase, db_conn::NOTIFQ ¬ifq) { bool b_normal = del_flags & DEL_MESSAGES; bool b_fai = del_flags & DEL_ASSOCIATED; @@ -624,11 +636,11 @@ static BOOL folder_empty_sf(db_conn_ptr &pdb, cpid_t cpid, const char *username, else if (!is_associated && pnormal_size != nullptr) *pnormal_size += sqlite3_column_int64(pstmt, 2); pdb->proc_dynamic_event(cpid, dynamic_event::del_msg, - folder_id, message_id, 0, *dbase); + folder_id, message_id, 0, *dbase, notifq); pdb->proc_dynamic_event(cpid, dynamic_event::del_msg, - parent_fid, message_id, 0, *dbase); - pdb->notify_link_deletion(folder_id, message_id, *dbase); - pdb->notify_message_deletion(parent_fid, message_id, *dbase); + parent_fid, message_id, 0, *dbase, notifq); + pdb->notify_link_deletion(folder_id, message_id, *dbase, notifq); + pdb->notify_message_deletion(parent_fid, message_id, *dbase, notifq); snprintf(sql_string, std::size(sql_string), "DELETE FROM messages " "WHERE message_id=%llu", LLU{message_id}); if (pdb->exec(sql_string) != SQLITE_OK) @@ -657,7 +669,8 @@ static BOOL folder_empty_sf(db_conn_ptr &pdb, cpid_t cpid, const char *username, static BOOL folder_empty_folder(db_conn_ptr &pdb, cpid_t cpid, const char *username, uint64_t folder_id, unsigned int del_flags, BOOL *pb_partial, uint64_t *pnormal_size, uint64_t *pfai_size, - uint32_t *pmessage_count, uint32_t *pfolder_count, db_base *dbase) + uint32_t *pmessage_count, uint32_t *pfolder_count, db_base *dbase, + db_conn::NOTIFQ ¬ifq) { bool b_hard = del_flags & DELETE_HARD_DELETE; bool b_normal = del_flags & DEL_MESSAGES; @@ -675,7 +688,7 @@ static BOOL folder_empty_folder(db_conn_ptr &pdb, cpid_t cpid, if (folder_type == FOLDER_SEARCH) return folder_empty_sf(pdb, cpid, username, folder_id, del_flags, pb_partial, pnormal_size, pfai_size, - pmessage_count, pfolder_count, dbase); + pmessage_count, pfolder_count, dbase, notifq); if (b_normal || b_fai) { auto ret = need_msg_perm_check(pdb->psqlite, username, folder_id); @@ -720,8 +733,8 @@ static BOOL folder_empty_folder(db_conn_ptr &pdb, cpid_t cpid, *pnormal_size += sqlite3_column_int64(pstmt, 1); if (0 == is_deleted) { pdb->proc_dynamic_event(cpid, dynamic_event::del_msg, - folder_id, message_id, 0, *dbase); - pdb->notify_message_deletion(folder_id, message_id, *dbase); + folder_id, message_id, 0, *dbase, notifq); + pdb->notify_message_deletion(folder_id, message_id, *dbase, notifq); } if (b_check) { if (b_hard) @@ -780,7 +793,7 @@ static BOOL folder_empty_folder(db_conn_ptr &pdb, cpid_t cpid, unsigned int new_flags = (del_flags & DELETE_HARD_DELETE) | DEL_MESSAGES | DEL_ASSOCIATED; if (!folder_empty_folder(pdb, cpid, username, fid_val, new_flags, &b_partial, pnormal_size, pfai_size, - nullptr, nullptr, dbase)) + nullptr, nullptr, dbase, notifq)) return FALSE; if (b_partial) { *pb_partial = TRUE; @@ -789,7 +802,7 @@ static BOOL folder_empty_folder(db_conn_ptr &pdb, cpid_t cpid, new_flags = (del_flags & DELETE_HARD_DELETE) | DEL_FOLDERS; if (!folder_empty_folder(pdb, cpid, username, fid_val, new_flags, &b_partial, pnormal_size, pfai_size, - nullptr, nullptr, dbase)) + nullptr, nullptr, dbase, notifq)) return FALSE; if (b_partial) { *pb_partial = TRUE; @@ -811,7 +824,7 @@ static BOOL folder_empty_folder(db_conn_ptr &pdb, cpid_t cpid, LLU{fid_val}); if (pdb->exec(sql_string) != SQLITE_OK) return FALSE; - pdb->notify_folder_deletion(folder_id, fid_val, *dbase); + pdb->notify_folder_deletion(folder_id, fid_val, *dbase, notifq); } return TRUE; } @@ -856,6 +869,8 @@ BOOL exmdb_server::delete_folder(const char *dir, cpid_t cpid, *pb_result = FALSE; return TRUE; } + + db_conn::NOTIFQ notifq; auto dbase = pdb->lock_base_wr(); if (!b_search) { /* Ensure that the folder has no subordinate folders and no messages. */ @@ -887,7 +902,7 @@ BOOL exmdb_server::delete_folder(const char *dir, cpid_t cpid, return FALSE; while (pstmt.step() == SQLITE_ROW) pdb->proc_dynamic_event(cpid, dynamic_event::del_msg, - fid_val, pstmt.col_int64(0), 0, *dbase); + fid_val, pstmt.col_int64(0), 0, *dbase, notifq); pstmt.finalize(); pdb->delete_dynamic(fid_val, dbase.get()); } @@ -907,7 +922,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.get()) || b_partial || + nullptr, nullptr, dbase.get(), notifq) || 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" @@ -952,8 +967,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(); + pdb->notify_folder_deletion(parent_id, fid_val, *dbase, notifq); /* Statistical updates for the parent folder */ snprintf(sql_string, std::size(sql_string), "UPDATE folder_properties SET" @@ -982,6 +996,7 @@ BOOL exmdb_server::delete_folder(const char *dir, cpid_t cpid, pstmt.finalize(); if (sql_transact.commit() != SQLITE_OK) return false; + dg_notify(std::move(notifq)); *pb_result = TRUE; return TRUE; } @@ -1009,12 +1024,13 @@ BOOL exmdb_server::empty_folder(const char *dir, cpid_t cpid, auto sql_transact = gx_sql_begin(pdb->psqlite, txn_mode::write); if (!sql_transact) return false; + + db_conn::NOTIFQ notifq; 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.get())) + &message_count, &folder_count, dbase.get(), notifq)) 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 " @@ -1051,7 +1067,10 @@ BOOL exmdb_server::empty_folder(const char *dir, cpid_t cpid, } if (!cu_adjust_store_size(pdb->psqlite, ADJ_DECREASE, normal_size, fai_size)) return FALSE; - return sql_transact.commit() == SQLITE_OK ? TRUE : false; + if (sql_transact.commit() != SQLITE_OK) + return false; + dg_notify(std::move(notifq)); + return TRUE; } /** @@ -1180,7 +1199,7 @@ static BOOL folder_copy_generic_folder(sqlite3 *psqlite, */ static BOOL folder_copy_search_folder(db_conn_ptr &pdb, cpid_t cpid, BOOL b_guest, const char *username, uint64_t src_fid, uint64_t dst_pid, - uint64_t *pdst_fid, db_base *dbase) + uint64_t *pdst_fid, db_base *dbase, db_conn::NOTIFQ ¬ifq) { uint32_t art; uint64_t nt_time; @@ -1264,7 +1283,7 @@ static BOOL folder_copy_search_folder(db_conn_ptr &pdb, cpid_t cpid, return FALSE; while (pstmt.step() == SQLITE_ROW) pdb->proc_dynamic_event(cpid, dynamic_event::new_msg, last_eid, - sqlite3_column_int64(pstmt, 0), 0, *dbase); + sqlite3_column_int64(pstmt, 0), 0, *dbase, notifq); *pdst_fid = last_eid; return TRUE; } @@ -1278,7 +1297,7 @@ static BOOL folder_copy_search_folder(db_conn_ptr &pdb, cpid_t cpid, static BOOL folder_copy_sf_int(db_conn_ptr &pdb, cpid_t cpid, bool b_guest, const char *username, uint64_t fid_val, bool b_normal, bool b_fai, uint64_t dst_fid, BOOL *pb_partial, uint64_t *pnormal_size, - uint64_t *pfai_size, db_base *dbase) + uint64_t *pfai_size, db_base *dbase, db_conn::NOTIFQ ¬ifq) { if (b_guest) { uint32_t permission = rightsNone; @@ -1348,7 +1367,7 @@ static BOOL folder_copy_sf_int(db_conn_ptr &pdb, cpid_t cpid, *pfai_size += message_size; } pdb->proc_dynamic_event(cpid, dynamic_event::new_msg, - dst_fid, message_id1, 0, *dbase); + dst_fid, message_id1, 0, *dbase, notifq); } return TRUE; } @@ -1363,7 +1382,7 @@ static BOOL folder_copy_folder_internal(db_conn_ptr &pdb, cpid_t cpid, BOOL b_guest, const char *username, uint64_t src_fid, BOOL b_normal, BOOL b_fai, BOOL b_sub, uint64_t dst_fid, BOOL *pb_partial, uint64_t *pnormal_size, uint64_t *pfai_size, uint32_t *pfolder_count, - db_base *dbase) + db_base *dbase, db_conn::NOTIFQ ¬ifq) { uint32_t folder_type = 0; *pb_partial = FALSE; @@ -1374,7 +1393,7 @@ static BOOL folder_copy_folder_internal(db_conn_ptr &pdb, if (folder_type == FOLDER_SEARCH) return folder_copy_sf_int(pdb, cpid, b_guest, username, fid_val, b_normal, b_fai, dst_fid, - pb_partial, pnormal_size, pfai_size, dbase); + pb_partial, pnormal_size, pfai_size, dbase, notifq); BOOL b_check = true, b_result, b_partial; char sql_string[132]; @@ -1437,7 +1456,7 @@ static BOOL folder_copy_folder_internal(db_conn_ptr &pdb, *pfai_size += message_size; } pdb->proc_dynamic_event(cpid, dynamic_event::new_msg, - dst_fid, message_id1, 0, *dbase); + dst_fid, message_id1, 0, *dbase, notifq); } } COPY_SUBFOLDER: @@ -1473,7 +1492,7 @@ static BOOL folder_copy_folder_internal(db_conn_ptr &pdb, return FALSE; if (folder_type == FOLDER_SEARCH) { if (!folder_copy_search_folder(pdb, cpid, - b_guest, username, fid_val, dst_fid, &fid_val, dbase)) + b_guest, username, fid_val, dst_fid, &fid_val, dbase, notifq)) return FALSE; } else { if (!folder_copy_generic_folder(pdb->psqlite, @@ -1490,7 +1509,8 @@ static BOOL folder_copy_folder_internal(db_conn_ptr &pdb, continue; if (!folder_copy_folder_internal(pdb, cpid, b_guest, username, src_fid1, TRUE, TRUE, TRUE, - fid_val, &b_partial, pnormal_size, pfai_size, nullptr, dbase)) + fid_val, &b_partial, pnormal_size, pfai_size, nullptr, + dbase, notifq)) return FALSE; if (b_partial) { *pb_partial = TRUE; @@ -1533,12 +1553,13 @@ BOOL exmdb_server::copy_folder_internal(const char *dir, cpid_t cpid, uint32_t folder_count = 0; uint64_t normal_size = 0, fai_size = 0; BOOL b_partial = false; + db_conn::NOTIFQ notifq; auto dbase = pdb->lock_base_wr(); if (!folder_copy_folder_internal(pdb, cpid, b_guest, username, src_val, b_normal, b_fai, b_sub, dst_val, - &b_partial, &normal_size, &fai_size, &folder_count, dbase.get())) + &b_partial, &normal_size, &fai_size, &folder_count, + dbase.get(), notifq)) 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 " @@ -1561,7 +1582,10 @@ BOOL exmdb_server::copy_folder_internal(const char *dir, cpid_t cpid, } if (!cu_adjust_store_size(pdb->psqlite, ADJ_INCREASE, normal_size, fai_size)) return FALSE; - return sql_transact.commit() == SQLITE_OK ? TRUE : false; + if (sql_transact.commit() != SQLITE_OK) + return false; + dg_notify(std::move(notifq)); + return TRUE; } /** @@ -1624,6 +1648,8 @@ BOOL exmdb_server::movecopy_folder(const char *dir, cpid_t cpid, BOOL b_guest, return TRUE; } } + + db_conn::NOTIFQ notifq; auto dbase = pdb->lock_base_wr(); if (!b_copy) { snprintf(sql_string, std::size(sql_string), "UPDATE folders SET parent_id=%llu" @@ -1663,13 +1689,14 @@ BOOL exmdb_server::movecopy_folder(const char *dir, cpid_t cpid, BOOL b_guest, return FALSE; fid_val = src_val; pdb->proc_dynamic_event(cpid, dynamic_event::move_folder, - parent_val, dst_val, src_val, *dbase); + parent_val, dst_val, src_val, *dbase, notifq); } else { if (!common_util_get_folder_type(pdb->psqlite, src_val, &folder_type)) return FALSE; if (folder_type == FOLDER_SEARCH) { if (!folder_copy_search_folder(pdb, cpid, - b_guest, username, src_val, dst_val, &fid_val, dbase.get())) + b_guest, username, src_val, dst_val, &fid_val, + dbase.get(), notifq)) return FALSE; } else { if (!folder_copy_generic_folder(pdb->psqlite, @@ -1691,7 +1718,8 @@ BOOL exmdb_server::movecopy_folder(const char *dir, cpid_t cpid, BOOL b_guest, BOOL b_partial = false; if (!folder_copy_folder_internal(pdb, cpid, b_guest, username, src_val, TRUE, TRUE, TRUE, - fid_val, &b_partial, &normal_size, &fai_size, nullptr, dbase.get())) + fid_val, &b_partial, &normal_size, &fai_size, + nullptr, dbase.get(), notifq)) return FALSE; if (!cu_adjust_store_size(pdb->psqlite, ADJ_INCREASE, normal_size, fai_size)) @@ -1714,10 +1742,11 @@ BOOL exmdb_server::movecopy_folder(const char *dir, cpid_t cpid, BOOL b_guest, LLU{nt_time}, LLU{dst_val}, PR_HIER_REV); 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(); + pdb->notify_folder_movecopy(b_copy, dst_val, fid_val, parent_val, + src_val, *dbase, notifq); if (sql_transact.commit() != SQLITE_OK) return false; + dg_notify(std::move(notifq)); *errcode = ecSuccess; return TRUE; } @@ -1795,7 +1824,7 @@ BOOL exmdb_server::get_search_criteria(const char *dir, uint64_t folder_id, } static BOOL folder_clear_search_folder(db_conn_ptr &pdb, - cpid_t cpid, uint64_t folder_id, db_base *dbase) + cpid_t cpid, uint64_t folder_id, db_base *dbase, db_conn::NOTIFQ ¬ifq) { char sql_string[128]; @@ -1806,7 +1835,7 @@ static BOOL folder_clear_search_folder(db_conn_ptr &pdb, return FALSE; while (pstmt.step() == SQLITE_ROW) pdb->proc_dynamic_event(cpid, dynamic_event::del_msg, - folder_id, pstmt.col_int64(0), 0, *dbase); + folder_id, pstmt.col_int64(0), 0, *dbase, notifq); pstmt.finalize(); snprintf(sql_string, std::size(sql_string), "DELETE FROM search_result" " WHERE folder_id=%llu", LLU{folder_id}); @@ -1932,11 +1961,14 @@ BOOL exmdb_server::set_search_criteria(const char *dir, cpid_t cpid, !common_util_load_search_scopes(pdb->psqlite, fid_val, &folder_ids)) return false; } + BOOL b_recursive = (search_flags & RECURSIVE_SEARCH) ? TRUE : false; BOOL b_update = false, b_populate = false; + db_conn::NOTIFQ notifq; auto dbase = pdb->lock_base_wr(); - if (!folder_clear_search_folder(pdb, cpid, fid_val, dbase.get())) + if (!folder_clear_search_folder(pdb, cpid, fid_val, dbase.get(), notifq)) return false; + dg_notify(std::move(notifq)); if (search_flags & RESTART_SEARCH) { b_populate = TRUE; if (!(search_flags & STATIC_SEARCH)) @@ -1949,7 +1981,6 @@ BOOL exmdb_server::set_search_criteria(const char *dir, cpid_t cpid, pdb->delete_dynamic(fid_val, dbase.get()); if (sql_transact.commit() != SQLITE_OK) return false; - pdb.reset(); if (b_populate && !db_engine_enqueue_populating_criteria(dir, cpid, fid_val, b_recursive, prestriction, &folder_ids)) diff --git a/exch/exmdb/message.cpp b/exch/exmdb/message.cpp index cdc59526b..2ebc432df 100644 --- a/exch/exmdb/message.cpp +++ b/exch/exmdb/message.cpp @@ -151,10 +151,12 @@ BOOL exmdb_server::movecopy_message(const char *dir, cpid_t cpid, uint64_t parent_fid = sqlite3_column_int64(pstmt, 0); bool is_associated = sqlite3_column_int64(pstmt, 1); pstmt.finalize(); + auto dbase = pdb->lock_base_wr(); + db_conn::NOTIFQ notifq; if (b_move) pdb->proc_dynamic_event(cpid, dynamic_event::del_msg, - parent_fid, mid_val, 0, *dbase); + parent_fid, mid_val, 0, *dbase, notifq); uint32_t message_size = 0; if (!cu_copy_message(pdb->psqlite, mid_val, fid_val, &dst_val, &b_result, &message_size)) @@ -162,10 +164,9 @@ BOOL exmdb_server::movecopy_message(const char *dir, cpid_t cpid, if (!b_result) return TRUE; pdb->proc_dynamic_event(cpid, - dynamic_event::new_msg, fid_val, dst_val, 0, *dbase); + dynamic_event::new_msg, fid_val, dst_val, 0, *dbase, notifq); pdb->notify_message_movecopy(!b_move ? TRUE : false, - fid_val, dst_val, parent_fid, mid_val, *dbase); - dbase.reset(); + fid_val, dst_val, parent_fid, mid_val, *dbase, notifq); BOOL b_update = TRUE; if (b_move) { if (exmdb_server::is_private()) { @@ -241,6 +242,7 @@ BOOL exmdb_server::movecopy_message(const char *dir, cpid_t cpid, PR_LOCAL_COMMIT_TIME_MAX, &nt_time, &b_result); if (sql_transact.commit() != SQLITE_OK) return false; + dg_notify(std::move(notifq)); *pb_result = TRUE; return TRUE; } @@ -284,8 +286,10 @@ BOOL exmdb_server::movecopy_messages(const char *dir, cpid_t cpid, BOOL b_guest, } else { b_check = TRUE; } + auto b_batch = pmessage_ids->count >= MIN_BATCH_MESSAGE_NUM; auto dbase = pdb->lock_base_wr(); + db_conn::NOTIFQ notifq; if (b_batch) pdb->begin_batch_mode(*dbase); auto cl_0 = make_scope_exit([&]() { @@ -357,9 +361,8 @@ BOOL exmdb_server::movecopy_messages(const char *dir, cpid_t cpid, BOOL b_guest, } } if (!b_copy) - pdb->proc_dynamic_event(cpid, - dynamic_event::del_msg, - parent_fid, tmp_val, 0, *dbase); + pdb->proc_dynamic_event(cpid, dynamic_event::del_msg, + parent_fid, tmp_val, 0, *dbase, notifq); uint64_t tmp_val1 = 0; if (!cu_copy_message(pdb->psqlite, tmp_val, dst_val, &tmp_val1, &b_result, &message_size)) @@ -373,8 +376,9 @@ BOOL exmdb_server::movecopy_messages(const char *dir, cpid_t cpid, BOOL b_guest, else fai_size += message_size; pdb->proc_dynamic_event(cpid, dynamic_event::new_msg, - dst_val, tmp_val1, 0, *dbase); - pdb->notify_message_movecopy(b_copy, dst_val, tmp_val1, src_val, tmp_val, *dbase); + dst_val, tmp_val1, 0, *dbase, notifq); + pdb->notify_message_movecopy(b_copy, dst_val, tmp_val1, + src_val, tmp_val, *dbase, notifq); if (b_copy) { mlog(LV_DEBUG, "exmdb-audit: copied(mmv) message %s:f%llu:m%llu to f%llu:m%llu", dir, LLU{src_val}, LLU{tmp_val}, LLU{dst_val}, LLU{tmp_val1}); @@ -453,6 +457,7 @@ BOOL exmdb_server::movecopy_messages(const char *dir, cpid_t cpid, BOOL b_guest, PR_LOCAL_COMMIT_TIME_MAX, &nt_time, &b_result); if (sql_transact.commit() != SQLITE_OK) return false; + dg_notify(std::move(notifq)); if (b_batch) { b_batch = false; db_conn::commit_batch_mode_release(std::move(pdb),std::move(dbase)); @@ -493,8 +498,10 @@ BOOL exmdb_server::delete_messages(const char *dir, cpid_t cpid, return FALSE; b_check = (permission & (frightsOwner | frightsDeleteAny)) ? false : TRUE; } + auto b_batch = pmessage_ids->count >= MIN_BATCH_MESSAGE_NUM; auto dbase = pdb->lock_base_wr(); + db_conn::NOTIFQ notifq; if (b_batch) pdb->begin_batch_mode(*dbase); auto cl_0 = make_scope_exit([&]() { @@ -558,11 +565,11 @@ BOOL exmdb_server::delete_messages(const char *dir, cpid_t cpid, else normal_size += obj_size; pdb->proc_dynamic_event(cpid, dynamic_event::del_msg, - parent_fid, tmp_val, 0, *dbase); + parent_fid, tmp_val, 0, *dbase, notifq); if (folder_type == FOLDER_SEARCH) - pdb->notify_link_deletion(src_val, tmp_val, *dbase); + pdb->notify_link_deletion(src_val, tmp_val, *dbase, notifq); else - pdb->notify_message_deletion(src_val, tmp_val, *dbase); + pdb->notify_message_deletion(src_val, tmp_val, *dbase, notifq); sqlite3_bind_int64(pstmt1, 1, tmp_val); if (pstmt1.step() != SQLITE_DONE) return FALSE; @@ -658,6 +665,7 @@ BOOL exmdb_server::delete_messages(const char *dir, cpid_t cpid, pdb->psqlite, src_val, del_count); if (sql_transact.commit() != SQLITE_OK) return false; + dg_notify(std::move(notifq)); if (b_batch) { b_batch = false; db_conn::commit_batch_mode_release(std::move(pdb), std::move(dbase)); @@ -931,13 +939,15 @@ 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->lock_base_wr(); + db_conn::NOTIFQ notifq; 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(); + fid_val, mid_val, 0, *dbase, notifq); + pdb->notify_message_modification(fid_val, mid_val, *dbase, notifq); if (sql_transact.commit() != SQLITE_OK) return false; + dg_notify(std::move(notifq)); return TRUE; } @@ -961,13 +971,15 @@ 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); + auto dbase = pdb->lock_base_wr(); - pdb->notify_message_modification(fid_val, mid_val, *dbase); + db_conn::NOTIFQ notifq; + pdb->notify_message_modification(fid_val, mid_val, *dbase, notifq); pdb->proc_dynamic_event(cpid, dynamic_event::modify_msg, - fid_val, mid_val, 0, *dbase); - dbase.reset(); + fid_val, mid_val, 0, *dbase, notifq); if (sql_transact.commit() != SQLITE_OK) return false; + dg_notify(std::move(notifq)); return TRUE; } @@ -1023,13 +1035,15 @@ 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->lock_base_wr(); + db_conn::NOTIFQ notifq; 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(); + fid_val, mid_val, 0, *dbase, notifq); + pdb->notify_message_modification(fid_val, mid_val, *dbase, notifq); if (sql_transact.commit() != SQLITE_OK) return false; + dg_notify(std::move(notifq)); *pread_cn = rop_util_make_eid_ex(1, read_cn); return TRUE; } @@ -1352,13 +1366,15 @@ 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->lock_base_wr(); + db_conn::NOTIFQ notifq; 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(); + fid_val, mid_val, 0, *dbase, notifq); + pdb->notify_link_creation(fid_val, mid_val, *dbase, notifq); if (sql_transact.commit() != SQLITE_OK) return FALSE; + dg_notify(std::move(notifq)); *pb_result = TRUE; return TRUE; } @@ -1380,13 +1396,15 @@ 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->lock_base_wr(); + db_conn::NOTIFQ notifq; 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(); + fid_val, mid_val, 0, *dbase, notifq); + pdb->notify_link_deletion(fid_val, mid_val, *dbase, notifq); if (pdb->exec(sql_string) != SQLITE_OK) return FALSE; + dg_notify(std::move(notifq)); return TRUE; } @@ -3726,19 +3744,27 @@ BOOL exmdb_server::deliver_message(const char *dir, const char *from_address, if (ec != ecSuccess) return FALSE; } + if (dlflags & DELIVERY_DO_NOTIF) { auto dbase = pdb->lock_base_wr(); + db_conn::NOTIFQ notifq; for (const auto &mn : seen.msg) { pdb->proc_dynamic_event(cpid, dynamic_event::new_msg, - mn.folder_id, mn.message_id, 0, *dbase); + mn.folder_id, mn.message_id, 0, *dbase, notifq); if (message_id == mn.message_id) - pdb->notify_new_mail(mn.folder_id, mn.message_id, *dbase); + pdb->notify_new_mail(mn.folder_id, + mn.message_id, *dbase, notifq); else - pdb->notify_message_creation(mn.folder_id, mn.message_id, *dbase); + pdb->notify_message_creation(mn.folder_id, + mn.message_id, *dbase, notifq); } + if (sql_transact.commit() != SQLITE_OK) + return false; + dg_notify(std::move(notifq)); + } else { + if (sql_transact.commit() != SQLITE_OK) + return false; } - if (sql_transact.commit() != SQLITE_OK) - return false; *new_folder_id = rop_util_make_eid_ex(1, fid_val); *new_msg_id = rop_util_make_eid_ex(1, message_id); *presult = static_cast(partial ? @@ -3810,18 +3836,19 @@ BOOL exmdb_server::write_message_v2(const char *dir, cpid_t cpid, } auto dbase = pdb->lock_base_wr(); + db_conn::NOTIFQ notifq; if (b_exist) { - pdb->proc_dynamic_event(cpid, - dynamic_event::modify_msg, fid_val, mid_val, 0, *dbase); - pdb->notify_message_modification(fid_val, mid_val, *dbase); + pdb->proc_dynamic_event(cpid, dynamic_event::modify_msg, + fid_val, mid_val, 0, *dbase, notifq); + pdb->notify_message_modification(fid_val, mid_val, *dbase, notifq); } else { - pdb->proc_dynamic_event(cpid, - dynamic_event::new_msg, fid_val, mid_val, 0, *dbase); - pdb->notify_message_creation(fid_val, mid_val, *dbase); + pdb->proc_dynamic_event(cpid, dynamic_event::new_msg, fid_val, + mid_val, 0, *dbase, notifq); + pdb->notify_message_creation(fid_val, mid_val, *dbase, notifq); } - dbase.reset(); if (sql_transact.commit() != SQLITE_OK) return false; + dg_notify(std::move(notifq)); *pe_result = ecSuccess; return TRUE; } @@ -3907,16 +3934,17 @@ BOOL exmdb_server::rule_new_message(const char *dir, const char *username, if (ec != ecSuccess) return FALSE; auto dbase = pdb->lock_base_wr(); + db_conn::NOTIFQ notifq; for (const auto &mn : seen.msg) { if (mid_val == mn.message_id) continue; pdb->proc_dynamic_event(cpid, dynamic_event::new_msg, - mn.folder_id, mn.message_id, 0, *dbase); - pdb->notify_message_creation(mn.folder_id, mn.message_id, *dbase); + mn.folder_id, mn.message_id, 0, *dbase, notifq); + pdb->notify_message_creation(mn.folder_id, mn.message_id, *dbase, notifq); } - dbase.reset(); if (sql_transact.commit() != SQLITE_OK) return false; + dg_notify(std::move(notifq)); return TRUE; } catch (const std::bad_alloc &) { mlog(LV_ERR, "E-2034: ENOMEM"); diff --git a/exch/exmdb/store.cpp b/exch/exmdb/store.cpp index 2df36c7f4..0422022fa 100644 --- a/exch/exmdb/store.cpp +++ b/exch/exmdb/store.cpp @@ -430,8 +430,12 @@ BOOL exmdb_server::transport_new_mail(const char *dir, uint64_t folder_id, if (!pdb) return FALSE; /* No database access, so no transaction. */ + auto dbase = pdb->lock_base_rd(); + db_conn::NOTIFQ notifq; pdb->transport_new_mail(rop_util_get_gc_value(folder_id), - rop_util_get_gc_value(message_id), message_flags, pstr_class, *pdb->lock_base_rd()); + rop_util_get_gc_value(message_id), message_flags, pstr_class, + *dbase, notifq); + dg_notify(std::move(notifq)); return TRUE; } diff --git a/exch/exmdb/store2.cpp b/exch/exmdb/store2.cpp index 8811869c6..3b10c288f 100644 --- a/exch/exmdb/store2.cpp +++ b/exch/exmdb/store2.cpp @@ -57,10 +57,13 @@ BOOL exmdb_server::notify_new_mail(const char *dir, uint64_t folder_id, auto pdb = db_engine_get_db(dir); if (!pdb) return false; - /* Notifications need an externally managed transaction on main. */ + /* notify_new_mail needs an externally managed transaction on main. */ auto sql_trans = gx_sql_begin(pdb->psqlite, txn_mode::read); + auto dbase = pdb->lock_base_wr(); + db_conn::NOTIFQ notifq; pdb->notify_new_mail(rop_util_get_gc_value(folder_id), - rop_util_get_gc_value(message_id), *pdb->lock_base_wr()); + rop_util_get_gc_value(message_id), *dbase, notifq); + dg_notify(std::move(notifq)); return TRUE; } @@ -143,7 +146,7 @@ static bool folder_purge_softdel(db_conn_ptr &db, cpid_t cpid, const char *username, uint64_t folder_id, unsigned int del_flags, bool *partial, uint64_t *normal_size, uint64_t *fai_size, uint32_t *msg_count, uint32_t *fld_count, mapitime_t cutoff, - const db_base *dbase) + const db_base *dbase, db_conn::NOTIFQ ¬ifq) { uint32_t folder_type = 0; if (!common_util_get_folder_type(db->psqlite, folder_id, &folder_type)) @@ -235,7 +238,7 @@ static bool folder_purge_softdel(db_conn_ptr &db, cpid_t cpid, bool sub_partial = false; if (!folder_purge_softdel(db, cpid, username, subfld, del_flags, &sub_partial, normal_size, fai_size, - msg_count, fld_count, cutoff, dbase)) + msg_count, fld_count, cutoff, dbase, notifq)) return false; if (sub_partial) { *partial = true; @@ -262,7 +265,7 @@ static bool folder_purge_softdel(db_conn_ptr &db, cpid_t cpid, "WHERE folder_id=%llu", LLU{subfld}); if (gx_sql_exec(db->psqlite, qstr) != SQLITE_OK) return false; - db->notify_folder_deletion(folder_id, subfld, *dbase); + db->notify_folder_deletion(folder_id, subfld, *dbase, notifq); } return true; } @@ -288,11 +291,13 @@ 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; + auto dbase = db->lock_base_wr(); + db_conn::NOTIFQ notifq; if (!folder_purge_softdel(db, CP_ACP, username, fid_val, del_flags, - &partial, &normal_size, &fai_size, &msg_count, &fld_count, cutoff, dbase.get())) + &partial, &normal_size, &fai_size, &msg_count, &fld_count, cutoff, + dbase.get(), notifq)) return false; - dbase.reset(); char qstr[116]; if (msg_count > 0) { snprintf(qstr, sizeof(qstr), "UPDATE folder_properties SET " @@ -328,7 +333,10 @@ BOOL exmdb_server::purge_softdelete(const char *dir, const char *username, } if (!cu_adjust_store_size(db->psqlite, ADJ_DECREASE, normal_size, fai_size)) return false; - return xact.commit() == SQLITE_OK ? TRUE : false; + if (xact.commit() != SQLITE_OK) + return false; + dg_notify(std::move(notifq)); + return TRUE; } static bool purg_discover_ids(sqlite3 *db, const std::string &query, diff --git a/exch/exmdb/table.cpp b/exch/exmdb/table.cpp index 4c969bee1..444ba3ed2 100644 --- a/exch/exmdb/table.cpp +++ b/exch/exmdb/table.cpp @@ -1070,6 +1070,7 @@ BOOL exmdb_server::reload_content_table(const char *dir, uint32_t table_id) if (!pdb) return FALSE; auto dbase = pdb->lock_base_wr(); + db_conn::NOTIFQ notifq; auto &table_list = dbase->tables.table_list; auto iter = std::find_if(table_list.begin(), table_list.end(), [&](const table_node &t) { @@ -1091,7 +1092,8 @@ BOOL exmdb_server::reload_content_table(const char *dir, uint32_t table_id) ptnode->folder_id, ptnode->username, ptnode->table_flags, ptnode->prestriction, ptnode->psorts, &table_id, &row_count); - pdb->notify_cttbl_reload(table_id, *dbase); + pdb->notify_cttbl_reload(table_id, *dbase, notifq); + dg_notify(std::move(notifq)); return b_result; } diff --git a/exch/midb/mail_engine.cpp b/exch/midb/mail_engine.cpp index 188519121..2889d26fb 100644 --- a/exch/midb/mail_engine.cpp +++ b/exch/midb/mail_engine.cpp @@ -1396,10 +1396,14 @@ static void mail_engine_insert_message(sqlite3_stmt *pstmt, uint32_t *puidnext, if (!exmdb_client::read_message(dir, nullptr, CP_ACP, rop_util_make_eid_ex(1, message_id), &pmsgctnt)) { common_util_switch_allocator(); + mlog(LV_ERR, "E-2394: read_message(%s,%llu) EXRPC failed", + dir, LLU{message_id}); return; } if (NULL == pmsgctnt) { common_util_switch_allocator(); + mlog(LV_ERR, "E-2398: read_message(%s,%llu) EXRPC: no message by this id", + dir, LLU{message_id}); return; } MAIL imail;