summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--plugins/Dbx_mdb/src/dbcontacts.cpp51
-rw-r--r--plugins/Dbx_mdb/src/dbintf.cpp61
-rw-r--r--plugins/Dbx_mdb/src/dbintf.h5
-rw-r--r--plugins/Dbx_mdb/src/dbmodulechain.cpp69
-rw-r--r--plugins/Dbx_mdb/src/dbsettings.cpp15
-rw-r--r--plugins/Dbx_mdb/src/lmdb/mdb.c2
6 files changed, 145 insertions, 58 deletions
diff --git a/plugins/Dbx_mdb/src/dbcontacts.cpp b/plugins/Dbx_mdb/src/dbcontacts.cpp
index ae960f8696..88a31f58d7 100644
--- a/plugins/Dbx_mdb/src/dbcontacts.cpp
+++ b/plugins/Dbx_mdb/src/dbcontacts.cpp
@@ -85,30 +85,30 @@ STDMETHODIMP_(LONG) CDbxMdb::DeleteContact(MCONTACT contactID)
NotifyEventHooks(hContactDeletedEvent, contactID, 0);
// delete
- mir_cslock lck(m_csDbAccess);
+ 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);
return 0;
}
STDMETHODIMP_(MCONTACT) CDbxMdb::AddContact()
{
- DWORD dwContactId;
- DBContact dbc = { 0 };
+ DBContact dbc;
dbc.signature = DBCONTACT_SIGNATURE;
- {
- mir_cslock lck(m_csDbAccess);
-
- dwContactId = m_dwMaxContactId++;
+ dbc.eventCount = 0;
+
+ DWORD dwContactId = m_dwMaxContactId++;
- MDB_val key, data;
- key.mv_size = sizeof(DWORD); key.mv_data = &dwContactId;
- data.mv_size = sizeof(DBContact); data.mv_data = &dbc;
+ 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);
- }
+ MDB_txn *txn;
+ mdb_txn_begin(m_pMdbEnv, NULL, 0, &txn);
+ mdb_put(txn, m_dbContacts, &key, &data, 0);
+ mdb_txn_commit(txn);
DBCachedContact *cc = m_cache->AddContactToCache(dwContactId);
cc->dwDriverData = 0;
@@ -120,17 +120,7 @@ STDMETHODIMP_(MCONTACT) CDbxMdb::AddContact()
STDMETHODIMP_(BOOL) CDbxMdb::IsDbContact(MCONTACT contactID)
{
DBCachedContact *cc = m_cache->GetCachedContact(contactID);
- if (cc == NULL)
- return FALSE;
-
- mir_cslock lck(m_csDbAccess);
- DBContact *dbc = NULL;
- if (dbc->signature == DBCONTACT_SIGNATURE) {
- m_cache->AddContactToCache(contactID);
- return TRUE;
- }
-
- return FALSE;
+ return (cc != NULL);
}
/////////////////////////////////////////////////////////////////////////////////////////
@@ -173,8 +163,11 @@ void CDbxMdb::FillContacts()
{
m_contactCount = 0;
+ MDB_txn *txn;
+ mdb_txn_begin(m_pMdbEnv, NULL, MDB_RDONLY, &txn);
+
MDB_cursor *cursor;
- mdb_cursor_open(m_txn, m_dbModules, &cursor);
+ mdb_cursor_open(txn, m_dbContacts, &cursor);
DWORD dwContactId;
DBContact value;
@@ -184,6 +177,9 @@ void CDbxMdb::FillContacts()
data.mv_size = sizeof(DBContact); data.mv_data = &value;
while (mdb_cursor_get(cursor, &key, &data, MDB_NEXT) == 0) {
+ if (value.signature != DBCONTACT_SIGNATURE)
+ DatabaseCorruption(NULL);
+
DBCachedContact *cc = m_cache->AddContactToCache(dwContactId);
cc->dwDriverData = 0;
CheckProto(cc, "");
@@ -206,4 +202,5 @@ 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 880c0c80fd..43a15b6457 100644
--- a/plugins/Dbx_mdb/src/dbintf.cpp
+++ b/plugins/Dbx_mdb/src/dbintf.cpp
@@ -95,11 +95,11 @@ int CDbxMdb::Load(bool bSkipInit)
return EGROKPRF_CANTREAD;
if (!bSkipInit) {
- mdb_txn_begin(m_pMdbEnv, NULL, 0, &m_txn);
-
- mdb_open(m_txn, "modules", MDB_CREATE | MDB_INTEGERKEY, &m_dbModules);
- mdb_open(m_txn, "contacts", MDB_CREATE | MDB_INTEGERKEY, &m_dbContacts);
- mdb_open(m_txn, "events", MDB_CREATE | MDB_INTEGERKEY, &m_dbEvents);
+ MDB_txn *txn;
+ mdb_txn_begin(m_pMdbEnv, NULL, 0, &txn);
+ mdb_open(txn, "contacts", MDB_CREATE | MDB_INTEGERKEY, &m_dbContacts);
+ mdb_open(txn, "events", MDB_CREATE | MDB_INTEGERKEY, &m_dbEvents);
+ mdb_txn_commit(txn);
if (InitModuleNames()) return EGROKPRF_CANTREAD;
if (InitCrypt()) return EGROKPRF_CANTREAD;
@@ -156,7 +156,7 @@ int CDbxMdb::Check(void)
return (memcmp(buf + 16, "\xDE\xC0\xEF\xBE", 4)) ? EGROKPRF_UNKHEADER : 0;
}
-int CDbxMdb::PrepareCheck(int *error)
+int CDbxMdb::PrepareCheck(int*)
{
InitModuleNames();
return InitCrypt();
@@ -168,6 +168,53 @@ STDMETHODIMP_(void) CDbxMdb::SetCacheSafetyMode(BOOL bIsSet)
m_safetyMode = bIsSet != 0;
}
+/////////////////////////////////////////////////////////////////////////////////////////
+
+static DWORD DatabaseCorrupted = 0;
+static const TCHAR *msg = NULL;
+static DWORD dwErr = 0;
+static TCHAR tszPanic[] = LPGENT("Miranda has detected corruption in your database. This corruption may be fixed by DbChecker plugin. Please download it from http://miranda-ng.org/p/DbChecker/. Miranda will now shut down.");
+
+void __cdecl dbpanic(void *)
+{
+ if (msg) {
+ if (dwErr == ERROR_DISK_FULL)
+ msg = TranslateT("Disk is full. Miranda will now shut down.");
+
+ TCHAR err[256];
+ mir_sntprintf(err, SIZEOF(err), msg, TranslateT("Database failure. Miranda will now shut down."), dwErr);
+
+ MessageBox(0, err, TranslateT("Database Error"), MB_SETFOREGROUND | MB_TOPMOST | MB_APPLMODAL | MB_ICONWARNING | MB_OK);
+ }
+ else MessageBox(0, TranslateTS(tszPanic), TranslateT("Database Panic"), MB_SETFOREGROUND | MB_TOPMOST | MB_APPLMODAL | MB_ICONWARNING | MB_OK);
+ TerminateProcess(GetCurrentProcess(), 255);
+}
+
+void CDbxMdb::DatabaseCorruption(const TCHAR *text)
+{
+ int kill = 0;
+
+ mir_cslockfull lck(m_csDbAccess);
+ if (DatabaseCorrupted == 0) {
+ DatabaseCorrupted++;
+ kill++;
+ msg = text;
+ dwErr = GetLastError();
+ }
+ else {
+ /* db is already corrupted, someone else is dealing with it, wait here
+ so that we don't do any more damage */
+ Sleep(INFINITE);
+ return;
+ }
+ lck.unlock();
+
+ if (kill) {
+ _beginthread(dbpanic, 0, NULL);
+ Sleep(INFINITE);
+ }
+}
+
///////////////////////////////////////////////////////////////////////////////
// MIDatabaseChecker
@@ -179,7 +226,7 @@ int CDbxMdb::Start(DBCHeckCallback *callback)
return ERROR_SUCCESS;
}
-int CDbxMdb::CheckDb(int phase, int firstTime)
+int CDbxMdb::CheckDb(int, int)
{
return ERROR_OUT_OF_PAPER;
diff --git a/plugins/Dbx_mdb/src/dbintf.h b/plugins/Dbx_mdb/src/dbintf.h
index cb1b238ee1..16f5a7de42 100644
--- a/plugins/Dbx_mdb/src/dbintf.h
+++ b/plugins/Dbx_mdb/src/dbintf.h
@@ -124,6 +124,8 @@ struct CDbxMdb : public MIDatabase, public MIDatabaseChecker, public MZeroedObje
int Create(void);
int Check(void);
+ void DatabaseCorruption(const TCHAR *ptszText);
+
void ToggleEncryption(void);
void StoreKey(void);
void SetPassword(const TCHAR *ptszPassword);
@@ -209,7 +211,6 @@ public:
protected:
MDB_env *m_pMdbEnv;
- MDB_txn *m_txn;
HANDLE hSettingChangeEvent, hContactDeletedEvent, hContactAddedEvent, hEventMarkedRead;
@@ -245,7 +246,7 @@ protected:
LIST<char> m_lResidentSettings;
HANDLE hEventAddedEvent, hEventDeletedEvent, hEventFilterAddedEvent;
MCONTACT m_hLastCachedContact;
- ModuleName *m_lastmn;
+ int m_maxModuleID;
void AddToList(char *name, DWORD ofs);
DWORD FindExistingModuleNameOfs(const char *szName);
diff --git a/plugins/Dbx_mdb/src/dbmodulechain.cpp b/plugins/Dbx_mdb/src/dbmodulechain.cpp
index 6f9a8fc15e..70e843111a 100644
--- a/plugins/Dbx_mdb/src/dbmodulechain.cpp
+++ b/plugins/Dbx_mdb/src/dbmodulechain.cpp
@@ -29,37 +29,57 @@ void CDbxMdb::AddToList(char *name, DWORD ofs)
mn->name = name;
mn->ofs = ofs;
+ if (m_lMods.getIndex(mn) != -1)
+ DatabaseCorruption(_T("%s (Module Name not unique)"));
m_lMods.insert(mn);
+
+ if (m_lOfs.getIndex(mn) != -1)
+ DatabaseCorruption(_T("%s (Module Offset not unique)"));
m_lOfs.insert(mn);
}
int CDbxMdb::InitModuleNames(void)
{
+ m_maxModuleID = 0;
+
+ MDB_txn *txn;
+ mdb_txn_begin(m_pMdbEnv, NULL, MDB_RDONLY, &txn);
+ mdb_open(txn, "modules", MDB_CREATE | MDB_INTEGERKEY, &m_dbModules);
+
MDB_cursor *cursor;
- mdb_cursor_open(m_txn, m_dbModules, &cursor);
+ mdb_cursor_open(txn, m_dbModules, &cursor);
int rc, moduleId;
- char moduleName[100];
- MDB_val key = { sizeof(int), &moduleId }, data = { sizeof(moduleName), moduleName };
- while ((rc = mdb_cursor_get(cursor, &key, &data, MDB_NEXT)) == 0)
- AddToList(moduleName, moduleId);
+ char valueBuf[100];
+ MDB_val key = { sizeof(int), &moduleId }, data = { sizeof(valueBuf), valueBuf };
+
+ while ((rc = mdb_cursor_get(cursor, &key, &data, MDB_NEXT)) == 0) {
+ DBModuleName *pmod = (DBModuleName*)valueBuf;
+ if (pmod->signature != DBMODULENAME_SIGNATURE)
+ DatabaseCorruption(NULL);
+
+ char *pVal = (char*)HeapAlloc(m_hModHeap, 0, pmod->cbName+1);
+ memcpy(pVal, pmod->name, pmod->cbName);
+ pVal[pmod->cbName] = 0;
+
+ AddToList(pVal, moduleId);
+
+ if (moduleId > m_maxModuleID)
+ m_maxModuleID = moduleId;
+ }
mdb_cursor_close(cursor);
+ mdb_txn_abort(txn);
return 0;
}
DWORD CDbxMdb::FindExistingModuleNameOfs(const char *szName)
{
ModuleName mn = { (char*)szName, 0 };
- if (m_lastmn && !strcmp(mn.name, m_lastmn->name))
- return m_lastmn->ofs;
int index = m_lMods.getIndex(&mn);
- if (index != -1) {
- ModuleName *pmn = m_lMods[index];
- m_lastmn = pmn;
- return pmn->ofs;
- }
+ if (index != -1)
+ return m_lMods[index]->ofs;
return 0;
}
@@ -77,11 +97,24 @@ DWORD CDbxMdb::GetModuleNameOfs(const char *szName)
int nameLen = (int)strlen(szName);
// need to create the module name
+ int newIdx = ++m_maxModuleID;
+ DBModuleName *pmod = (DBModuleName*)_alloca(sizeof(DBModuleName) + nameLen);
+ pmod->signature = DBMODULENAME_SIGNATURE;
+ pmod->cbName = (char)nameLen;
+ strcpy(pmod->name, 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);
// add to cache
char *mod = (char*)HeapAlloc(m_hModHeap, 0, nameLen + 1);
strcpy(mod, szName);
- AddToList(mod, -1);
+ AddToList(mod, newIdx);
// quit
return -1;
@@ -89,16 +122,10 @@ DWORD CDbxMdb::GetModuleNameOfs(const char *szName)
char* CDbxMdb::GetModuleNameByOfs(DWORD ofs)
{
- if (m_lastmn && m_lastmn->ofs == ofs)
- return m_lastmn->name;
-
ModuleName mn = { NULL, ofs };
int index = m_lOfs.getIndex(&mn);
- if (index != -1) {
- ModuleName *pmn = m_lOfs[index];
- m_lastmn = pmn;
- return pmn->name;
- }
+ if (index != -1)
+ return m_lOfs[index]->name;
return NULL;
}
diff --git a/plugins/Dbx_mdb/src/dbsettings.cpp b/plugins/Dbx_mdb/src/dbsettings.cpp
index 46d3540185..099625a1d2 100644
--- a/plugins/Dbx_mdb/src/dbsettings.cpp
+++ b/plugins/Dbx_mdb/src/dbsettings.cpp
@@ -79,6 +79,7 @@ int CDbxMdb::GetContactSettingWorker(MCONTACT contactID, LPCSTR szModule, LPCSTR
mir_cslock lck(m_csDbAccess);
+LBL_Seek:
char *szCachedSettingName = m_cache->GetCachedSetting(szModule, szSetting, moduleNameLen, settingNameLen);
log3("get [%08p] %s (%p)", hContact, szCachedSettingName, szCachedSettingName);
@@ -116,6 +117,20 @@ int CDbxMdb::GetContactSettingWorker(MCONTACT contactID, LPCSTR szModule, LPCSTR
if (szCachedSettingName[-1] != 0)
return 1;
+ 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;
+ }
+ }
+ }
+
return 1;
}
diff --git a/plugins/Dbx_mdb/src/lmdb/mdb.c b/plugins/Dbx_mdb/src/lmdb/mdb.c
index f6fd68b1cc..996683cd08 100644
--- a/plugins/Dbx_mdb/src/lmdb/mdb.c
+++ b/plugins/Dbx_mdb/src/lmdb/mdb.c
@@ -216,7 +216,7 @@ union semun {
#ifdef _WIN32
#define MDB_USE_HASH 1
#define MDB_PIDLOCK 0
-#define THREAD_RET DWORD
+#define THREAD_RET DWORD WINAPI
#define pthread_t HANDLE
#define pthread_mutex_t HANDLE
#define pthread_cond_t HANDLE