diff options
author | George Hazan <george.hazan@gmail.com> | 2015-01-12 23:00:18 +0000 |
---|---|---|
committer | George Hazan <george.hazan@gmail.com> | 2015-01-12 23:00:18 +0000 |
commit | 88722c0734ae6ce9b91ba397b89c4b73ed6f064d (patch) | |
tree | f7015fc820d7ec94dcea7f9e4511edcb9d6bce69 /plugins/Dbx_mdb | |
parent | 3f5208b9147b32ddcf259ec8bb3fb280192928f8 (diff) |
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
Diffstat (limited to 'plugins/Dbx_mdb')
-rw-r--r-- | plugins/Dbx_mdb/src/commonheaders.h | 30 | ||||
-rw-r--r-- | plugins/Dbx_mdb/src/dbcontacts.cpp | 22 | ||||
-rw-r--r-- | plugins/Dbx_mdb/src/dbintf.cpp | 8 | ||||
-rw-r--r-- | plugins/Dbx_mdb/src/dbintf.h | 8 | ||||
-rw-r--r-- | plugins/Dbx_mdb/src/dbmodulechain.cpp | 19 | ||||
-rw-r--r-- | plugins/Dbx_mdb/src/dbsettings.cpp | 204 |
6 files changed, 257 insertions, 34 deletions
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<CDbxMdb> 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 <pshpack1.h>
+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)
|