From 88722c0734ae6ce9b91ba397b89c4b73ed6f064d Mon Sep 17 00:00:00 2001 From: George Hazan Date: Mon, 12 Jan 2015 23:00:18 +0000 Subject: transaction locker very first version of settings writer/reader git-svn-id: http://svn.miranda-ng.org/main/trunk@11847 1316c22d-e87f-b044-9b9b-93d7a3e3ba9c --- plugins/Dbx_mdb/src/commonheaders.h | 30 +++++ plugins/Dbx_mdb/src/dbcontacts.cpp | 22 ++-- plugins/Dbx_mdb/src/dbintf.cpp | 8 ++ plugins/Dbx_mdb/src/dbintf.h | 8 ++ plugins/Dbx_mdb/src/dbmodulechain.cpp | 19 ++-- plugins/Dbx_mdb/src/dbsettings.cpp | 204 ++++++++++++++++++++++++++++++++-- 6 files changed, 257 insertions(+), 34 deletions(-) (limited to 'plugins/Dbx_mdb/src') diff --git a/plugins/Dbx_mdb/src/commonheaders.h b/plugins/Dbx_mdb/src/commonheaders.h index 57db50bdb3..ecc4347629 100644 --- a/plugins/Dbx_mdb/src/commonheaders.h +++ b/plugins/Dbx_mdb/src/commonheaders.h @@ -56,6 +56,36 @@ extern "C" extern HINSTANCE g_hInst; extern LIST g_Dbs; +class txn_lock +{ + MDB_txn *txn; + +public: + __forceinline txn_lock(MDB_env *pEnv) + { mdb_txn_begin(pEnv, NULL, 0, &txn); + } + + __forceinline ~txn_lock() + { + if (txn) + mdb_txn_abort(txn); + } + + __forceinline operator MDB_txn*() const { return txn; } + + __forceinline void commit() + { + mdb_txn_commit(txn); + txn = NULL; + } + + __forceinline void abort() + { + mdb_txn_abort(txn); + txn = NULL; + } +}; + #ifdef __GNUC__ #define mir_i64(x) (x##LL) #else diff --git a/plugins/Dbx_mdb/src/dbcontacts.cpp b/plugins/Dbx_mdb/src/dbcontacts.cpp index fbb3c89276..26c245e8cb 100644 --- a/plugins/Dbx_mdb/src/dbcontacts.cpp +++ b/plugins/Dbx_mdb/src/dbcontacts.cpp @@ -87,10 +87,9 @@ STDMETHODIMP_(LONG) CDbxMdb::DeleteContact(MCONTACT contactID) // delete MDB_val key = { sizeof(DWORD), &contactID }; - MDB_txn *txn; - mdb_txn_begin(m_pMdbEnv, NULL, 0, &txn); - mdb_del(txn, m_dbContacts, &key, NULL); - mdb_txn_commit(txn); + txn_lock trnlck(m_pMdbEnv); + mdb_del(trnlck, m_dbContacts, &key, NULL); + trnlck.commit(); return 0; } @@ -105,10 +104,9 @@ STDMETHODIMP_(MCONTACT) CDbxMdb::AddContact() MDB_val key = { sizeof(DWORD), &dwContactId }; MDB_val data = { sizeof(DBContact), &dbc }; - MDB_txn *txn; - mdb_txn_begin(m_pMdbEnv, NULL, 0, &txn); - mdb_put(txn, m_dbContacts, &key, &data, 0); - mdb_txn_commit(txn); + txn_lock trnlck(m_pMdbEnv); + mdb_put(trnlck, m_dbContacts, &key, &data, 0); + trnlck.commit(); DBCachedContact *cc = m_cache->AddContactToCache(dwContactId); cc->dwDriverData = 0; @@ -163,12 +161,11 @@ void CDbxMdb::FillContacts() { m_contactCount = 0; - MDB_txn *txn; - mdb_txn_begin(m_pMdbEnv, NULL, MDB_RDONLY, &txn); - mdb_open(txn, "contacts", MDB_CREATE | MDB_INTEGERKEY, &m_dbContacts); + txn_lock trnlck(m_pMdbEnv); + mdb_open(trnlck, "contacts", MDB_INTEGERKEY, &m_dbContacts); MDB_cursor *cursor; - mdb_cursor_open(txn, m_dbContacts, &cursor); + mdb_cursor_open(trnlck, m_dbContacts, &cursor); MDB_val key, data; while (mdb_cursor_get(cursor, &key, &data, MDB_NEXT) == 0) { @@ -199,5 +196,4 @@ void CDbxMdb::FillContacts() } mdb_cursor_close(cursor); - mdb_txn_abort(txn); } diff --git a/plugins/Dbx_mdb/src/dbintf.cpp b/plugins/Dbx_mdb/src/dbintf.cpp index f646273100..52e5083e75 100644 --- a/plugins/Dbx_mdb/src/dbintf.cpp +++ b/plugins/Dbx_mdb/src/dbintf.cpp @@ -51,6 +51,7 @@ CDbxMdb::CDbxMdb(const TCHAR *tszFileName, int iMode) : InitDbInstance(this); mdb_env_create(&m_pMdbEnv); + mdb_env_set_mapsize(m_pMdbEnv, 65536); mdb_env_set_maxdbs(m_pMdbEnv, 10); m_codePage = CallService(MS_LANGPACK_GETCODEPAGE, 0, 0); @@ -95,6 +96,13 @@ int CDbxMdb::Load(bool bSkipInit) return EGROKPRF_CANTREAD; if (!bSkipInit) { + txn_lock trnlck(m_pMdbEnv); + mdb_open(trnlck, "contacts", MDB_CREATE | MDB_INTEGERKEY, &m_dbContacts); + mdb_open(trnlck, "modules", MDB_CREATE | MDB_INTEGERKEY, &m_dbModules); + mdb_open(trnlck, "events", MDB_CREATE | MDB_INTEGERKEY, &m_dbEvents); + mdb_open(trnlck, "settings", MDB_CREATE, &m_dbSettings); + trnlck.commit(); + if (InitModuleNames()) return EGROKPRF_CANTREAD; if (InitCrypt()) return EGROKPRF_CANTREAD; diff --git a/plugins/Dbx_mdb/src/dbintf.h b/plugins/Dbx_mdb/src/dbintf.h index 16f5a7de42..78507969df 100644 --- a/plugins/Dbx_mdb/src/dbintf.h +++ b/plugins/Dbx_mdb/src/dbintf.h @@ -80,6 +80,13 @@ struct ModuleName #include +struct DBSettingKey +{ + DWORD dwContactID; + DWORD dwOfsModule; + char szSettingName[100]; +}; + #define DBCONTACT_SIGNATURE 0x43DECADEu struct DBContact { @@ -221,6 +228,7 @@ protected: //////////////////////////////////////////////////////////////////////////// // settings + MDB_dbi m_dbSettings; int m_codePage; HANDLE hService, hHook; diff --git a/plugins/Dbx_mdb/src/dbmodulechain.cpp b/plugins/Dbx_mdb/src/dbmodulechain.cpp index 59b2b8d509..4643a2d295 100644 --- a/plugins/Dbx_mdb/src/dbmodulechain.cpp +++ b/plugins/Dbx_mdb/src/dbmodulechain.cpp @@ -42,13 +42,12 @@ int CDbxMdb::InitModuleNames(void) { m_maxModuleID = 0; - MDB_txn *txn; - mdb_txn_begin(m_pMdbEnv, NULL, 0, &txn); - mdb_open(txn, "modules", MDB_CREATE | MDB_INTEGERKEY, &m_dbModules); - mdb_open(txn, "events", MDB_CREATE | MDB_INTEGERKEY, &m_dbEvents); + txn_lock trnlck(m_pMdbEnv); + mdb_open(trnlck, "modules", MDB_INTEGERKEY, &m_dbModules); MDB_cursor *cursor; - mdb_cursor_open(txn, m_dbModules, &cursor); + if (mdb_cursor_open(trnlck, m_dbModules, &cursor) != MDB_SUCCESS) + return 1; MDB_val key, data; @@ -69,7 +68,6 @@ int CDbxMdb::InitModuleNames(void) } mdb_cursor_close(cursor); - mdb_txn_abort(txn); return 0; } @@ -105,11 +103,10 @@ DWORD CDbxMdb::GetModuleNameOfs(const char *szName) MDB_val key = { sizeof(int), &newIdx }, data = { sizeof(DBModuleName) + nameLen, pmod }; - MDB_txn *txn; - mdb_txn_begin(m_pMdbEnv, NULL, 0, &txn); - mdb_open(txn, "modules", MDB_CREATE | MDB_INTEGERKEY, &m_dbModules); - mdb_put(txn, m_dbModules, &key, &data, 0); - mdb_txn_commit(txn); + txn_lock trnlck(m_pMdbEnv); + mdb_open(trnlck, "modules", MDB_INTEGERKEY, &m_dbModules); + mdb_put(trnlck, m_dbModules, &key, &data, 0); + trnlck.commit(); // add to cache char *mod = (char*)HeapAlloc(m_hModHeap, 0, nameLen + 1); diff --git a/plugins/Dbx_mdb/src/dbsettings.cpp b/plugins/Dbx_mdb/src/dbsettings.cpp index 099625a1d2..7b0825d8c9 100644 --- a/plugins/Dbx_mdb/src/dbsettings.cpp +++ b/plugins/Dbx_mdb/src/dbsettings.cpp @@ -119,19 +119,117 @@ LBL_Seek: DBCachedContact *cc = (contactID) ? m_cache->GetCachedContact(contactID) : NULL; - DWORD ofsModuleName = GetModuleNameOfs(szModule); - - // try to get the missing mc setting from the active sub - if (cc && cc->IsMeta() && ValidLookupName(szModule, szSetting)) { - if (contactID = db_mc_getDefault(contactID)) { - if (szModule = GetContactProto(contactID)) { - moduleNameLen = (int)strlen(szModule); - goto LBL_Seek; + txn_lock trnlck(m_pMdbEnv); + mdb_open(trnlck, "settings", 0, &m_dbSettings); + + DBSettingKey keySearch; + keySearch.dwContactID = contactID; + keySearch.dwOfsModule = GetModuleNameOfs(szModule); + strncpy_s(keySearch.szSettingName, szSetting, _TRUNCATE); + + MDB_val key = { 2 * sizeof(DWORD) + settingNameLen, &keySearch }, data; + if (mdb_get(trnlck, m_dbSettings, &key, &data)) { + // try to get the missing mc setting from the active sub + if (cc && cc->IsMeta() && ValidLookupName(szModule, szSetting)) { + if (contactID = db_mc_getDefault(contactID)) { + if (szModule = GetContactProto(contactID)) { + moduleNameLen = (int)strlen(szModule); + goto LBL_Seek; + } + } + } + return 1; + } + + BYTE *pBlob = (BYTE*)data.mv_data; + if (isStatic && (pBlob[0] & DBVTF_VARIABLELENGTH) && VLT(dbv->type) != VLT(pBlob[0])) + return 1; + + int varLen; + BYTE iType = dbv->type = pBlob[0]; + switch (iType) { + case DBVT_DELETED: /* this setting is deleted */ + dbv->type = DBVT_DELETED; + return 2; + + case DBVT_BYTE: dbv->bVal = pBlob[1]; break; + case DBVT_WORD: memmove(&(dbv->wVal), (PWORD)(pBlob + 1), 2); break; + case DBVT_DWORD: memmove(&(dbv->dVal), (PDWORD)(pBlob + 1), 4); break; + + case DBVT_UTF8: + case DBVT_ASCIIZ: + varLen = *(PWORD)(pBlob + 1); + pBlob += 3 + varLen; + if (isStatic) { + dbv->cchVal--; + if (varLen < dbv->cchVal) + dbv->cchVal = varLen; + memmove(dbv->pszVal, pBlob + 3, dbv->cchVal); // decode + dbv->pszVal[dbv->cchVal] = 0; + dbv->cchVal = varLen; + } + else { + dbv->pszVal = (char*)mir_alloc(1 + varLen); + memmove(dbv->pszVal, pBlob + 3, varLen); + dbv->pszVal[varLen] = 0; + } + break; + + case DBVT_BLOB: + varLen = *(PWORD)(pBlob + 1); + pBlob += 3 + varLen; + if (isStatic) { + if (varLen < dbv->cpbVal) + dbv->cpbVal = varLen; + memmove(dbv->pbVal, pBlob + 3, dbv->cpbVal); + } + else { + dbv->pbVal = (BYTE *)mir_alloc(varLen); + memmove(dbv->pbVal, pBlob + 3, varLen); + } + dbv->cpbVal = varLen; + break; + + case DBVT_ENCRYPTED: + if (m_crypto == NULL) + return 1; + else { + varLen = *(PWORD)(pBlob + 1); + pBlob += 3 + varLen; + size_t realLen; + ptrA decoded(m_crypto->decodeString(pBlob + 3, varLen, &realLen)); + if (decoded == NULL) + return 1; + + varLen = (WORD)realLen; + dbv->type = DBVT_UTF8; + if (isStatic) { + dbv->cchVal--; + if (varLen < dbv->cchVal) + dbv->cchVal = varLen; + memmove(dbv->pszVal, decoded, dbv->cchVal); + dbv->pszVal[dbv->cchVal] = 0; + dbv->cchVal = varLen; + } + else { + dbv->pszVal = (char*)mir_alloc(1 + varLen); + memmove(dbv->pszVal, decoded, varLen); + dbv->pszVal[varLen] = 0; } } + break; } - return 1; + /**** add to cache **********************/ + if (iType != DBVT_BLOB && iType != DBVT_ENCRYPTED) { + DBVARIANT *pCachedValue = m_cache->GetCachedValuePtr(contactID, szCachedSettingName, 1); + if (pCachedValue != NULL) { + m_cache->SetCachedVariant(dbv, pCachedValue); + log3("set cached [%08p] %s (%p)", hContact, szCachedSettingName, pCachedValue); + } + } + + return 0; } STDMETHODIMP_(BOOL) CDbxMdb::GetContactSetting(MCONTACT contactID, LPCSTR szModule, LPCSTR szSetting, DBVARIANT *dbv) @@ -375,6 +473,54 @@ STDMETHODIMP_(BOOL) CDbxMdb::WriteContactSetting(MCONTACT contactID, DBCONTACTWR } else m_cache->GetCachedValuePtr(contactID, szCachedSettingName, -1); + txn_lock trnlck(m_pMdbEnv); + mdb_open(trnlck, "settings", 0, &m_dbSettings); + + DBSettingKey keySearch; + keySearch.dwContactID = contactID; + keySearch.dwOfsModule = GetModuleNameOfs(dbcws->szModule); + strncpy_s(keySearch.szSettingName, dbcws->szSetting, _TRUNCATE); + + MDB_val key = { 2 * sizeof(DWORD) + settingNameLen, &keySearch }, data; + + switch (dbcwWork.value.type) { + case DBVT_BYTE: data.mv_size = 2; break; + case DBVT_WORD: data.mv_size = 3; break; + case DBVT_DWORD: data.mv_size = 5; break; + + case DBVT_ASCIIZ: + case DBVT_UTF8: + data.mv_size = 3 + dbcwWork.value.cchVal; break; + + case DBVT_BLOB: + case DBVT_ENCRYPTED: + data.mv_size = 3 + dbcwWork.value.cpbVal; break; + } + + if (mdb_put(trnlck, m_dbSettings, &key, &data, MDB_RESERVE) != 0) + return 1; + + BYTE *pBlob = (BYTE*)data.mv_data; + *pBlob++ = dbcwWork.value.type; + switch (dbcwWork.value.type) { + case DBVT_BYTE: *pBlob = dbcwWork.value.bVal; break; + case DBVT_WORD: *(WORD*)pBlob = dbcwWork.value.wVal; break; + case DBVT_DWORD: *(DWORD*)pBlob = dbcwWork.value.dVal; break; + + case DBVT_ASCIIZ: + case DBVT_UTF8: + data.mv_size = *(WORD*)pBlob = dbcwWork.value.cchVal; + pBlob += 2; + memcpy(pBlob, dbcwWork.value.pszVal, dbcwWork.value.cchVal); + break; + + case DBVT_BLOB: + case DBVT_ENCRYPTED: + data.mv_size = *(WORD*)pBlob = dbcwWork.value.cpbVal; + pBlob += 2; + memcpy(pBlob, dbcwWork.value.pbVal, dbcwWork.value.cpbVal); + } + lck.unlock(); // notify @@ -408,6 +554,19 @@ STDMETHODIMP_(BOOL) CDbxMdb::DeleteContactSetting(MCONTACT contactID, LPCSTR szM mir_cslock lck(m_csDbAccess); char *szCachedSettingName = m_cache->GetCachedSetting(szModule, szSetting, moduleNameLen, settingNameLen); if (szCachedSettingName[-1] == 0) { // it's not a resident variable + txn_lock trnlck(m_pMdbEnv); + mdb_open(trnlck, "settings", 0, &m_dbSettings); + + DBSettingKey keySearch; + keySearch.dwContactID = contactID; + keySearch.dwOfsModule = GetModuleNameOfs(szModule); + strncpy_s(keySearch.szSettingName, szSetting, _TRUNCATE); + + MDB_val key = { 2 * sizeof(DWORD) + settingNameLen, &keySearch }, data; + if (mdb_del(trnlck, m_dbSettings, &key, &data)) + return 1; + + trnlck.commit(); } m_cache->GetCachedValuePtr(saveContact, szCachedSettingName, -1); @@ -427,8 +586,33 @@ STDMETHODIMP_(BOOL) CDbxMdb::EnumContactSettings(MCONTACT contactID, DBCONTACTEN if (!dbces->szModule) return -1; + int result = 0; mir_cslock lck(m_csDbAccess); - return -11; + /* + txn_lock trnlck(m_pMdbEnv); + mdb_open(trnlck, "settings", 0, &m_dbSettings); + + MDB_cursor *cursor; + mdb_cursor_open(trnlck, m_dbSettings, &cursor); + + DBSettingKey keySearch; + keySearch.dwContactID = contactID; + keySearch.dwOfsModule = GetModuleNameOfs(dbces->szModule); + keySearch.szSettingName[0] = 0; + + MDB_val key = { 2 * sizeof(DWORD), &keySearch }, data; + while (mdb_cursor_get(cursor, &key, &data, MDB_NEXT) == 0) { + DBSettingKey *pKey = (DBSettingKey*)key.mv_data; + if (pKey->dwContactID != contactID || pKey->dwOfsModule != keySearch.dwOfsModule) + break; + + char szSetting[256]; + strncpy_s(szSetting, pKey->szSettingName, key.mv_size - sizeof(DWORD)*2); + result = (dbces->pfnEnumProc)(szSetting, dbces->lParam); + } + + mdb_cursor_close(cursor); */ + return result; } STDMETHODIMP_(BOOL) CDbxMdb::EnumResidentSettings(DBMODULEENUMPROC pFunc, void *pParam) -- cgit v1.2.3