From 2868202cb6260735157346833a4cf6326772011d Mon Sep 17 00:00:00 2001 From: MikalaiR Date: Thu, 18 Feb 2016 12:32:59 +0000 Subject: dbx_lmdb: speed optimization git-svn-id: http://svn.miranda-ng.org/main/trunk@16301 1316c22d-e87f-b044-9b9b-93d7a3e3ba9c --- plugins/Dbx_mdb/src/dbcontacts.cpp | 18 +++++++++- plugins/Dbx_mdb/src/dbevents.cpp | 65 ++++++++++++++++++----------------- plugins/Dbx_mdb/src/dbintf.cpp | 28 +++++++++++++-- plugins/Dbx_mdb/src/dbintf.h | 3 +- plugins/Dbx_mdb/src/dbmodulechain.cpp | 4 +-- plugins/Dbx_mdb/src/dbsettings.cpp | 4 +-- plugins/Dbx_mdb/src/stdafx.h | 31 ++++++++++++----- 7 files changed, 103 insertions(+), 50 deletions(-) (limited to 'plugins/Dbx_mdb') diff --git a/plugins/Dbx_mdb/src/dbcontacts.cpp b/plugins/Dbx_mdb/src/dbcontacts.cpp index 4bfec0261c..554df02d9a 100644 --- a/plugins/Dbx_mdb/src/dbcontacts.cpp +++ b/plugins/Dbx_mdb/src/dbcontacts.cpp @@ -104,6 +104,22 @@ STDMETHODIMP_(LONG) CDbxMdb::DeleteContact(MCONTACT contactID) if (trnlck.commit()) break; } + + DBEventSortingKey keyVal = { 0, 0, contactID }; + key = { sizeof(keyVal), &keyVal }; MDB_val data; + + txn_ptr trnlck(m_pMdbEnv, true); + cursor_ptr cursor(trnlck, m_dbEventsSort); + mdb_cursor_get(cursor, &key, &data, MDB_SET); + while (mdb_cursor_get(cursor, &key, &data, MDB_NEXT) == MDB_SUCCESS) + { + DBEventSortingKey *pKey = (DBEventSortingKey*)key.mv_data; + if (pKey->dwContactId != contactID) + return 0; + + mdb_cursor_del(cursor, 0); + } + return 0; } @@ -159,7 +175,7 @@ void CDbxMdb::GatherContactHistory(MCONTACT hContact, LIST &list) DBEventSortingKey keyVal = { 0, 0, hContact }; MDB_val key = { sizeof(keyVal), &keyVal }, data; - txn_ptr trnlck(m_pMdbEnv, true); + txn_ptr_ro trnlck(m_pMdbEnv); cursor_ptr cursor(trnlck, m_dbEventsSort); mdb_cursor_get(cursor, &key, &data, MDB_SET); while (mdb_cursor_get(cursor, &key, &data, MDB_NEXT) == MDB_SUCCESS) { diff --git a/plugins/Dbx_mdb/src/dbevents.cpp b/plugins/Dbx_mdb/src/dbevents.cpp index dd9a75e12f..d8c5a37d6d 100644 --- a/plugins/Dbx_mdb/src/dbevents.cpp +++ b/plugins/Dbx_mdb/src/dbevents.cpp @@ -23,6 +23,8 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. #include "stdafx.h" +MDB_txn* txn_ptr_ro::m_txn; + STDMETHODIMP_(LONG) CDbxMdb::GetEventCount(MCONTACT contactID) { DBCachedContact *cc = m_cache->GetCachedContact(contactID); @@ -82,7 +84,7 @@ STDMETHODIMP_(MEVENT) CDbxMdb::AddEvent(MCONTACT contactID, DBEVENTINFO *dbei) mir_cslockfull lck(m_csDbAccess); DWORD dwEventId = ++m_dwMaxEventId; - for (;; Remap()) { + for (bool bContactIncremented = false; ;[=](){ if (bContactIncremented) cc->dbc.dwEventCount--; }(), Remap()) { txn_ptr txn(m_pMdbEnv); MDB_val key = { sizeof(int), &dwEventId }, data = { sizeof(DBEvent) + dbe.cbBlob, NULL }; @@ -99,6 +101,7 @@ STDMETHODIMP_(MEVENT) CDbxMdb::AddEvent(MCONTACT contactID, DBEVENTINFO *dbei) MDB_CHECK(mdb_put(txn, m_dbEventsSort, &key, &data, 0), 0); cc->Advance(dwEventId, dbe); + bContactIncremented = true; MDB_val keyc = { sizeof(int), &contactID }, datac = { sizeof(DBContact), &cc->dbc }; MDB_CHECK(mdb_put(txn, m_dbContacts, &keyc, &datac, 0), 0); @@ -133,51 +136,56 @@ STDMETHODIMP_(BOOL) CDbxMdb::DeleteEvent(MCONTACT contactID, MEVENT hDbEvent) return 1; mir_cslockfull lck(m_csDbAccess); - txn_ptr txn(m_pMdbEnv); - - for (;; Remap()) { + + for (bool bContactDecremented = false; ;[=](){ if (bContactDecremented) cc->dbc.dwEventCount++; }(), Remap()) + { + txn_ptr txn(m_pMdbEnv); MDB_val key = { sizeof(MEVENT), &hDbEvent }, data; - if (mdb_get(txn, m_dbEvents, &key, &data) != MDB_SUCCESS) - return 1; + MDB_CHECK(mdb_get(txn, m_dbEvents, &key, &data), 1); DBEvent *dbe = (DBEvent*)data.mv_data; DWORD dwSavedContact = dbe->contactID; DBEventSortingKey key2 = { hDbEvent, dbe->timestamp, contactID }; - mdb_del(txn, m_dbEvents, &key, &data); // remove a sorting key key.mv_size = sizeof(key2); key.mv_data = &key2; - mdb_del(txn, m_dbEventsSort, &key, &data); + MDB_CHECK(mdb_del(txn, m_dbEventsSort, &key, &data), 1) // remove a sub's history entry too if (contactID != dwSavedContact) { key2.dwContactId = dwSavedContact; - mdb_del(txn, m_dbEventsSort, &key, &data); + MDB_CHECK(mdb_del(txn, m_dbEventsSort, &key, &data), 1); } + // remove a event + key = { sizeof(MEVENT), &hDbEvent }; + MDB_CHECK(mdb_del(txn, m_dbEvents, &key, &data), 1); + // update a contact key.mv_size = sizeof(int); key.mv_data = &contactID; cc->dbc.dwEventCount--; + bContactDecremented = true; if (cc->dbc.dwFirstUnread == hDbEvent) FindNextUnread(txn, cc, key2); + + data = { sizeof(DBContact), &cc->dbc }; + + MDB_CHECK(mdb_put(txn, m_dbContacts, &key, &data, 0), 0); if (txn.commit()) break; } lck.unlock(); - // call notifier while outside mutex NotifyEventHooks(hEventDeletedEvent, contactID, hDbEvent); - // get back in - lck.lock(); return 0; } STDMETHODIMP_(LONG) CDbxMdb::GetBlobSize(MEVENT hDbEvent) { mir_cslock lck(m_csDbAccess); - txn_ptr txn(m_pMdbEnv, true); + txn_ptr_ro txn(m_pMdbEnv); MDB_val key = { sizeof(MEVENT), &hDbEvent }, data; if (mdb_get(txn, m_dbEvents, &key, &data) != MDB_SUCCESS) @@ -196,7 +204,7 @@ STDMETHODIMP_(BOOL) CDbxMdb::GetEvent(MEVENT hDbEvent, DBEVENTINFO *dbei) } mir_cslock lck(m_csDbAccess); - txn_ptr txn(m_pMdbEnv, true); + txn_ptr_ro txn(m_pMdbEnv); MDB_val key = { sizeof(MEVENT), &hDbEvent }, data; if (mdb_get(txn, m_dbEvents, &key, &data) != MDB_SUCCESS) @@ -210,11 +218,13 @@ STDMETHODIMP_(BOOL) CDbxMdb::GetEvent(MEVENT hDbEvent, DBEVENTINFO *dbei) dbei->timestamp = dbe->timestamp; dbei->flags = dbe->flags; dbei->eventType = dbe->wEventType; - int bytesToCopy = (dbei->cbBlob < dbe->cbBlob) ? dbei->cbBlob : dbe->cbBlob; + size_t bytesToCopy = min(dbei->cbBlob, dbe->cbBlob); dbei->cbBlob = dbe->cbBlob; - if (bytesToCopy && dbei->pBlob) { + if (bytesToCopy && dbei->pBlob) + { BYTE *pSrc = (BYTE*)data.mv_data + sizeof(DBEvent); - if (dbe->flags & DBEF_ENCRYPTED) { + if (dbe->flags & DBEF_ENCRYPTED) + { dbei->flags &= ~DBEF_ENCRYPTED; size_t len; BYTE* pBlob = (BYTE*)m_crypto->decodeBuffer(pSrc, dbe->cbBlob, &len); @@ -222,7 +232,7 @@ STDMETHODIMP_(BOOL) CDbxMdb::GetEvent(MEVENT hDbEvent, DBEVENTINFO *dbei) return 1; memcpy(dbei->pBlob, pBlob, bytesToCopy); - if (bytesToCopy > (int)len) + if (bytesToCopy > len) memset(dbei->pBlob + len, 0, bytesToCopy - len); mir_free(pBlob); } @@ -294,7 +304,7 @@ STDMETHODIMP_(MCONTACT) CDbxMdb::GetEventContact(MEVENT hDbEvent) if (hDbEvent == 0) return INVALID_CONTACT_ID; mir_cslock lck(m_csDbAccess); - txn_ptr txn(m_pMdbEnv, true); + txn_ptr_ro txn(m_pMdbEnv); MDB_val key = { sizeof(MEVENT), &hDbEvent }, data; if (mdb_get(txn, m_dbEvents, &key, &data) != MDB_SUCCESS) @@ -310,7 +320,7 @@ STDMETHODIMP_(MEVENT) CDbxMdb::FindFirstEvent(MCONTACT contactID) MDB_val key = { sizeof(keyVal), &keyVal }, data; mir_cslock lck(m_csDbAccess); - txn_ptr txn(m_pMdbEnv, true); + txn_ptr_ro txn(m_pMdbEnv); cursor_ptr cursor(txn, m_dbEventsSort); mdb_cursor_get(cursor, &key, &data, MDB_SET); @@ -334,7 +344,7 @@ STDMETHODIMP_(MEVENT) CDbxMdb::FindLastEvent(MCONTACT contactID) MDB_val key = { sizeof(keyVal), &keyVal }, data; mir_cslock lck(m_csDbAccess); - txn_ptr txn(m_pMdbEnv, true); + txn_ptr_ro txn(m_pMdbEnv); cursor_ptr cursor(txn, m_dbEventsSort); mdb_cursor_get(cursor, &key, &data, MDB_SET); @@ -354,7 +364,7 @@ STDMETHODIMP_(MEVENT) CDbxMdb::FindNextEvent(MCONTACT contactID, MEVENT hDbEvent DWORD ts; mir_cslock lck(m_csDbAccess); - txn_ptr txn(m_pMdbEnv, true); + txn_ptr_ro txn(m_pMdbEnv); if (m_evLast != hDbEvent) { MDB_val key = { sizeof(MEVENT), &hDbEvent }; @@ -387,7 +397,7 @@ STDMETHODIMP_(MEVENT) CDbxMdb::FindPrevEvent(MCONTACT contactID, MEVENT hDbEvent DWORD ts; mir_cslock lck(m_csDbAccess); - txn_ptr txn(m_pMdbEnv, true); + txn_ptr_ro txn(m_pMdbEnv); if (m_evLast != hDbEvent) { MDB_val key = { sizeof(MEVENT), &hDbEvent }; @@ -411,12 +421,3 @@ STDMETHODIMP_(MEVENT) CDbxMdb::FindPrevEvent(MCONTACT contactID, MEVENT hDbEvent m_tsLast = pKey->ts; return m_evLast = (pKey->dwContactId == contactID) ? pKey->dwEventId : 0; } - -///////////////////////////////////////////////////////////////////////////////////////// -// low-level history cleaner - -int CDbxMdb::WipeContactHistory(DBContact*) -{ - // drop subContact's history if any - return 0; -} diff --git a/plugins/Dbx_mdb/src/dbintf.cpp b/plugins/Dbx_mdb/src/dbintf.cpp index 503746369e..b7c0c81572 100644 --- a/plugins/Dbx_mdb/src/dbintf.cpp +++ b/plugins/Dbx_mdb/src/dbintf.cpp @@ -23,6 +23,18 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. #include "stdafx.h" +#define CMP_UINT32(A,B) if (A != B) return (A < B) ? -1 : 1; + +static int MDB_CompareEvents(const MDB_val *v1, const MDB_val *v2) +{ + DBEventSortingKey *k1 = static_cast(v1->mv_data); + DBEventSortingKey *k2 = static_cast(v2->mv_data); + CMP_UINT32(k1->dwContactId, k2->dwContactId); + CMP_UINT32(k1->ts, k2->ts); + CMP_UINT32(k1->dwEventId, k2->dwEventId); + return 0; +} + static int ModCompare(const ModuleName *mn1, const ModuleName *mn2) { return strcmp(mn1->name, mn2->name); @@ -85,11 +97,12 @@ CDbxMdb::~CDbxMdb() int CDbxMdb::Load(bool bSkipInit) { - if (!Remap()) + if (!Map()) return EGROKPRF_CANTREAD; if (!bSkipInit) { txn_ptr trnlck(m_pMdbEnv); + mdb_open(trnlck, "global", MDB_CREATE | MDB_INTEGERKEY, &m_dbGlobal); mdb_open(trnlck, "contacts", MDB_CREATE | MDB_INTEGERKEY, &m_dbContacts); mdb_open(trnlck, "modules", MDB_CREATE | MDB_INTEGERKEY, &m_dbModules); @@ -97,6 +110,8 @@ int CDbxMdb::Load(bool bSkipInit) mdb_open(trnlck, "eventsrt", MDB_CREATE | MDB_INTEGERKEY, &m_dbEventsSort); mdb_open(trnlck, "settings", MDB_CREATE, &m_dbSettings); + //mdb_set_compare(trnlck, m_dbEventsSort, MDB_CompareEvents); + DWORD keyVal = 1; MDB_val key = { sizeof(DWORD), &keyVal }, data; if (mdb_get(trnlck, m_dbGlobal, &key, &data) == MDB_SUCCESS) { @@ -146,7 +161,7 @@ int CDbxMdb::Load(bool bSkipInit) int CDbxMdb::Create(void) { m_dwFileSize = 0; - return (Remap()) ? 0 : EGROKPRF_CANTREAD; + return (Map()) ? 0 : EGROKPRF_CANTREAD; } int CDbxMdb::Check(void) @@ -182,7 +197,7 @@ STDMETHODIMP_(void) CDbxMdb::SetCacheSafetyMode(BOOL bIsSet) m_safetyMode = bIsSet != 0; } -bool CDbxMdb::Remap() +bool CDbxMdb::Map() { m_dwFileSize += 0x100000; mdb_env_set_mapsize(m_pMdbEnv, m_dwFileSize); @@ -195,6 +210,13 @@ bool CDbxMdb::Remap() return mdb_env_open(m_pMdbEnv, _T2A(m_tszProfileName), mode, 0664) == MDB_SUCCESS; } +bool CDbxMdb::Remap() +{ + mir_cslock lck(m_csDbAccess); + m_dwFileSize += 0x100000; + return mdb_env_set_mapsize(m_pMdbEnv, m_dwFileSize) == MDB_SUCCESS; +} + ///////////////////////////////////////////////////////////////////////////////////////// static DWORD DatabaseCorrupted = 0; diff --git a/plugins/Dbx_mdb/src/dbintf.h b/plugins/Dbx_mdb/src/dbintf.h index 30dd786bb9..866b637786 100644 --- a/plugins/Dbx_mdb/src/dbintf.h +++ b/plugins/Dbx_mdb/src/dbintf.h @@ -205,7 +205,7 @@ protected: void FillContacts(void); bool Remap(); - + bool Map(); public: // Check functions int WorkInitialChecks(int); int WorkModuleChain(int); @@ -248,7 +248,6 @@ protected: MDB_dbi m_dbContacts; int m_contactCount, m_dwMaxContactId; - int WipeContactHistory(DBContact *dbc); void GatherContactHistory(MCONTACT hContact, LIST &items); //////////////////////////////////////////////////////////////////////////// diff --git a/plugins/Dbx_mdb/src/dbmodulechain.cpp b/plugins/Dbx_mdb/src/dbmodulechain.cpp index 1ab0971b20..a91ccc576c 100644 --- a/plugins/Dbx_mdb/src/dbmodulechain.cpp +++ b/plugins/Dbx_mdb/src/dbmodulechain.cpp @@ -42,8 +42,8 @@ int CDbxMdb::InitModuleNames(void) { m_maxModuleID = 0; - txn_ptr trnlck(m_pMdbEnv); - mdb_open(trnlck, "modules", MDB_INTEGERKEY, &m_dbModules); + txn_ptr_ro trnlck(m_pMdbEnv); + //mdb_open(trnlck, "modules", MDB_INTEGERKEY, &m_dbModules); cursor_ptr cursor(trnlck, m_dbModules); if (!cursor) diff --git a/plugins/Dbx_mdb/src/dbsettings.cpp b/plugins/Dbx_mdb/src/dbsettings.cpp index 89750b8fc7..ebfe1970b4 100644 --- a/plugins/Dbx_mdb/src/dbsettings.cpp +++ b/plugins/Dbx_mdb/src/dbsettings.cpp @@ -121,7 +121,7 @@ LBL_Seek: DBCachedContact *cc = (contactID) ? m_cache->GetCachedContact(contactID) : NULL; - txn_ptr trnlck(m_pMdbEnv); + txn_ptr_ro trnlck(m_pMdbEnv); //mdb_open(trnlck, "settings", 0, &m_dbSettings); DBSettingKey keySearch; @@ -597,7 +597,7 @@ STDMETHODIMP_(BOOL) CDbxMdb::EnumContactSettings(MCONTACT contactID, DBCONTACTEN LIST arSettings(50); { - txn_ptr trnlck(m_pMdbEnv, true); + txn_ptr_ro trnlck(m_pMdbEnv); cursor_ptr cursor(trnlck, m_dbSettings); MDB_val key = { sizeof(keySearch), &keySearch }, data; diff --git a/plugins/Dbx_mdb/src/stdafx.h b/plugins/Dbx_mdb/src/stdafx.h index dd06f5806a..ee324a69ee 100644 --- a/plugins/Dbx_mdb/src/stdafx.h +++ b/plugins/Dbx_mdb/src/stdafx.h @@ -21,13 +21,6 @@ along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ -#define _CRT_SECURE_NO_WARNINGS -#define _WIN32_WINNT 0x0501 - -#pragma warning(disable:4509) - -//#define SIZEOF(x) _countof(x) - #include #include #include @@ -83,12 +76,34 @@ public: } }; +class txn_ptr_ro +{ + static MDB_txn *m_txn; + +public: + __forceinline txn_ptr_ro(MDB_env *pEnv) + { + if (!m_txn) + mdb_txn_begin(pEnv, NULL, MDB_RDONLY, &m_txn); + else + mdb_txn_renew(m_txn); + } + + __forceinline ~txn_ptr_ro() + { + if (m_txn) + mdb_txn_reset(m_txn); + } + + __forceinline operator MDB_txn*() const { return m_txn; } +}; + class cursor_ptr { MDB_cursor *m_cursor; public: - __forceinline cursor_ptr(const txn_ptr &_txn, MDB_dbi _dbi) + __forceinline cursor_ptr(MDB_txn *_txn, MDB_dbi _dbi) { if (mdb_cursor_open(_txn, _dbi, &m_cursor) != MDB_SUCCESS) m_cursor = NULL; -- cgit v1.2.3