summaryrefslogtreecommitdiff
path: root/plugins
diff options
context:
space:
mode:
authorGeorge Hazan <ghazan@miranda.im>2018-03-30 16:47:09 +0300
committerGeorge Hazan <ghazan@miranda.im>2018-03-30 16:47:09 +0300
commit0a8a140351a533e2fb895228589efd2846b9c697 (patch)
treeea9b92130b2f6ab7304e496f20f8b88e0d7ca78f /plugins
parent3166b70501ec138496e04140f82147ea23d82420 (diff)
fix for asynchronous database flush to fix unsaved data
Diffstat (limited to 'plugins')
-rw-r--r--plugins/Dbx_mdbx/src/dbcontacts.cpp6
-rw-r--r--plugins/Dbx_mdbx/src/dbcrypt.cpp3
-rw-r--r--plugins/Dbx_mdbx/src/dbevents.cpp4
-rw-r--r--plugins/Dbx_mdbx/src/dbintf.cpp24
-rw-r--r--plugins/Dbx_mdbx/src/dbintf.h130
-rw-r--r--plugins/Dbx_mdbx/src/dbmodulechain.cpp1
-rw-r--r--plugins/Dbx_mdbx/src/dbsettings.cpp4
7 files changed, 106 insertions, 66 deletions
diff --git a/plugins/Dbx_mdbx/src/dbcontacts.cpp b/plugins/Dbx_mdbx/src/dbcontacts.cpp
index 24faa109fc..aa3a27f8f2 100644
--- a/plugins/Dbx_mdbx/src/dbcontacts.cpp
+++ b/plugins/Dbx_mdbx/src/dbcontacts.cpp
@@ -77,6 +77,7 @@ STDMETHODIMP_(LONG) CDbxMDBX::DeleteContact(MCONTACT contactID)
// free cache item
m_cache->FreeCachedContact(contactID);
+ DBFlush();
InterlockedDecrement(&m_contactCount);
return 0;
@@ -98,6 +99,7 @@ STDMETHODIMP_(MCONTACT) CDbxMDBX::AddContact()
return 0;
}
+ DBFlush();
InterlockedIncrement(&m_contactCount);
NotifyEventHooks(hContactAddedEvent, dwContactId, 0);
return dwContactId;
@@ -155,6 +157,8 @@ BOOL CDbxMDBX::MetaMergeHistory(DBCachedContact *ccMeta, DBCachedContact *ccSub)
return 1;
if (trnlck.commit() != MDBX_SUCCESS)
return 1;
+
+ DBFlush();
return 0;
}
@@ -185,6 +189,8 @@ BOOL CDbxMDBX::MetaSplitHistory(DBCachedContact *ccMeta, DBCachedContact *ccSub)
return 1;
if (trnlck.commit() != MDBX_SUCCESS)
return 1;
+
+ DBFlush();
return 0;
}
diff --git a/plugins/Dbx_mdbx/src/dbcrypt.cpp b/plugins/Dbx_mdbx/src/dbcrypt.cpp
index 0a6585e565..e22b3a293d 100644
--- a/plugins/Dbx_mdbx/src/dbcrypt.cpp
+++ b/plugins/Dbx_mdbx/src/dbcrypt.cpp
@@ -62,6 +62,7 @@ CRYPTO_PROVIDER* CDbxMDBX::SelectProvider()
return nullptr;
}
+ DBFlush();
return pProv;
}
@@ -137,6 +138,7 @@ void CDbxMDBX::StoreKey()
}
SecureZeroMemory(pKey, iKeyLength);
+ DBFlush();
}
void CDbxMDBX::SetPassword(const wchar_t *ptszPassword)
@@ -228,6 +230,7 @@ int CDbxMDBX::EnableEncryption(bool bEncrypted)
if (trnlck.commit() != MDBX_SUCCESS)
return 1;
+ DBFlush();
m_bEncrypted = bEncrypted;
return 0;
}
diff --git a/plugins/Dbx_mdbx/src/dbevents.cpp b/plugins/Dbx_mdbx/src/dbevents.cpp
index 4ad32afe54..ad8d478b73 100644
--- a/plugins/Dbx_mdbx/src/dbevents.cpp
+++ b/plugins/Dbx_mdbx/src/dbevents.cpp
@@ -134,6 +134,8 @@ STDMETHODIMP_(MEVENT) CDbxMDBX::AddEvent(MCONTACT contactID, DBEVENTINFO *dbei)
return 0;
}
+ DBFlush();
+
// Notify only in safe mode or on really new events
if (m_safetyMode)
NotifyEventHooks(hEventAddedEvent, contactNotifyID, dwEventId);
@@ -214,6 +216,7 @@ STDMETHODIMP_(BOOL) CDbxMDBX::DeleteEvent(MCONTACT contactID, MEVENT hDbEvent)
return 1;
}
+ DBFlush();
NotifyEventHooks(hEventDeletedEvent, contactID, hDbEvent);
return 0;
}
@@ -340,6 +343,7 @@ STDMETHODIMP_(BOOL) CDbxMDBX::MarkEventRead(MCONTACT contactID, MEVENT hDbEvent)
return -1;
}
+ DBFlush();
NotifyEventHooks(hEventMarkedRead, contactID, (LPARAM)hDbEvent);
return wRetVal;
}
diff --git a/plugins/Dbx_mdbx/src/dbintf.cpp b/plugins/Dbx_mdbx/src/dbintf.cpp
index 79f5f0a4f1..b94edd4845 100644
--- a/plugins/Dbx_mdbx/src/dbintf.cpp
+++ b/plugins/Dbx_mdbx/src/dbintf.cpp
@@ -95,6 +95,7 @@ int CDbxMDBX::Load(bool bSkipInit)
m_header.dwVersion = DBHEADER_VERSION;
data.iov_base = &m_header; data.iov_len = sizeof(m_header);
mdbx_put(trnlck, m_dbGlobal, &key, &data, 0);
+ DBFlush();
}
keyVal = 2;
@@ -183,6 +184,7 @@ int CDbxMDBX::PrepareCheck()
STDMETHODIMP_(void) CDbxMDBX::SetCacheSafetyMode(BOOL bIsSet)
{
m_safetyMode = bIsSet != 0;
+ DBFlush(true);
}
int CDbxMDBX::Map()
@@ -203,3 +205,25 @@ int CDbxMDBX::Map()
int exclusive = (m_bShared) ? 1 : 2;
return mdbx_env_open_ex(m_env, _T2A(m_tszProfileName), mode, 0664, &exclusive);
}
+
+/////////////////////////////////////////////////////////////////////////////////////////
+
+static VOID CALLBACK DoBufferFlushTimerProc(HWND, UINT, UINT_PTR idEvent, DWORD)
+{
+ KillTimer(nullptr, idEvent);
+
+ for (auto &it : g_Dbs)
+ if (it->m_timerId == idEvent)
+ it->DBFlush(true);
+}
+
+void CDbxMDBX::DBFlush(bool bForce)
+{
+ if (bForce) {
+ mdbx_env_sync(m_env, true);
+ }
+ else if (m_safetyMode) {
+ ::KillTimer(nullptr, m_timerId);
+ ::SetTimer(nullptr, m_timerId, 50, DoBufferFlushTimerProc);
+ }
+}
diff --git a/plugins/Dbx_mdbx/src/dbintf.h b/plugins/Dbx_mdbx/src/dbintf.h
index d858deeb3e..a1e4c992c7 100644
--- a/plugins/Dbx_mdbx/src/dbintf.h
+++ b/plugins/Dbx_mdbx/src/dbintf.h
@@ -129,17 +129,10 @@ struct EventItem
MEVENT eventId;
};
-struct CDbxMDBX : public MDatabaseCommon, public MZeroedObject
+class CDbxMDBX : public MDatabaseCommon, public MZeroedObject
{
friend class MDBXEventCursor;
- CDbxMDBX(const TCHAR *tszFileName, int mode);
- virtual ~CDbxMDBX();
-
- int Load(bool bSkipInit);
- int Create(void);
- int Check(void);
-
__forceinline MDBX_txn* StartTran() const
{
MDBX_txn *res = 0;
@@ -150,66 +143,17 @@ struct CDbxMDBX : public MDatabaseCommon, public MZeroedObject
return res;
}
- void StoreKey(void);
- void SetPassword(const wchar_t *ptszPassword);
- void UpdateMenuItem(void);
-
+ void FillContacts(void);
+ int Map();
int PrepareCheck();
+ void UpdateMenuItem(void);
- __forceinline LPSTR GetMenuTitle() const { return m_bUsesPassword ? (char*)LPGEN("Change/remove password") : (char*)LPGEN("Set password"); }
-
- __forceinline bool isEncrypted() const { return m_bEncrypted; }
- __forceinline bool usesPassword() const { return m_bUsesPassword; }
- int EnableEncryption(bool bEnable);
-public:
- STDMETHODIMP_(BOOL) IsRelational(void) { return TRUE; }
- STDMETHODIMP_(void) SetCacheSafetyMode(BOOL);
-
- STDMETHODIMP_(LONG) GetContactCount(void);
- STDMETHODIMP_(LONG) DeleteContact(MCONTACT contactID);
- STDMETHODIMP_(MCONTACT) AddContact(void);
- STDMETHODIMP_(BOOL) IsDbContact(MCONTACT contactID);
- STDMETHODIMP_(LONG) GetContactSize(void);
-
- STDMETHODIMP_(LONG) GetEventCount(MCONTACT contactID);
- STDMETHODIMP_(MEVENT) AddEvent(MCONTACT contactID, DBEVENTINFO *dbe);
- STDMETHODIMP_(BOOL) DeleteEvent(MCONTACT contactID, MEVENT hDbEvent);
- STDMETHODIMP_(LONG) GetBlobSize(MEVENT hDbEvent);
- STDMETHODIMP_(BOOL) GetEvent(MEVENT hDbEvent, DBEVENTINFO *dbe);
- STDMETHODIMP_(BOOL) MarkEventRead(MCONTACT contactID, MEVENT hDbEvent);
- STDMETHODIMP_(MCONTACT) GetEventContact(MEVENT hDbEvent);
- STDMETHODIMP_(MEVENT) FindFirstEvent(MCONTACT contactID);
- STDMETHODIMP_(MEVENT) FindFirstUnreadEvent(MCONTACT contactID);
- STDMETHODIMP_(MEVENT) FindLastEvent(MCONTACT contactID);
- STDMETHODIMP_(MEVENT) FindNextEvent(MCONTACT contactID, MEVENT hDbEvent);
- STDMETHODIMP_(MEVENT) FindPrevEvent(MCONTACT contactID, MEVENT hDbEvent);
-
- STDMETHODIMP_(BOOL) EnumModuleNames(DBMODULEENUMPROC pFunc, void *pParam);
-
- STDMETHODIMP_(BOOL) GetContactSettingWorker(MCONTACT contactID, LPCSTR szModule, LPCSTR szSetting, DBVARIANT *dbv, int isStatic);
- STDMETHODIMP_(BOOL) WriteContactSetting(MCONTACT contactID, DBCONTACTWRITESETTING *dbcws);
- STDMETHODIMP_(BOOL) DeleteContactSetting(MCONTACT contactID, LPCSTR szModule, LPCSTR szSetting);
- STDMETHODIMP_(BOOL) EnumContactSettings(MCONTACT hContact, DBSETTINGENUMPROC pfnEnumProc, const char *szModule, void *param);
-
- STDMETHODIMP_(BOOL) MetaMergeHistory(DBCachedContact *ccMeta, DBCachedContact *ccSub);
- STDMETHODIMP_(BOOL) MetaSplitHistory(DBCachedContact *ccMeta, DBCachedContact *ccSub);
-
-protected:
-
- void FillContacts(void);
-
- int Map();
+ ////////////////////////////////////////////////////////////////////////////
+ // database stuff
-protected:
TCHAR* m_tszProfileName;
bool m_safetyMode, m_bReadOnly, m_bShared, m_bEncrypted, m_bUsesPassword;
- ////////////////////////////////////////////////////////////////////////////
- // database stuff
-public:
- MICryptoEngine *m_crypto;
-
-protected:
MDBX_env *m_env;
CMDBX_txn_ro m_txn_ro;
@@ -241,7 +185,7 @@ protected:
////////////////////////////////////////////////////////////////////////////
// events
- MDBX_dbi m_dbEvents, m_dbEventsSort;
+ MDBX_dbi m_dbEvents, m_dbEventsSort;
MDBX_cursor *m_curEvents, *m_curEventsSort;
MEVENT m_dwMaxEventId;
@@ -254,11 +198,11 @@ protected:
MDBX_dbi m_dbModules;
MDBX_cursor *m_curModules;
-
+
std::map<uint32_t, std::string> m_Modules;
int InitModules();
-
+
uint32_t GetModuleID(const char *szName);
char* GetModuleName(uint32_t dwId);
@@ -271,4 +215,58 @@ protected:
CRYPTO_PROVIDER* SelectProvider();
void InitDialogs();
-}; \ No newline at end of file
+
+public:
+ CDbxMDBX(const TCHAR *tszFileName, int mode);
+ virtual ~CDbxMDBX();
+
+ int Check(void);
+ int Create(void);
+ void DBFlush(bool bForce = false);
+ int EnableEncryption(bool bEnable);
+ int Load(bool bSkipInit);
+ void StoreKey(void);
+ void SetPassword(const wchar_t *ptszPassword);
+
+ __forceinline LPSTR GetMenuTitle() const { return m_bUsesPassword ? (char*)LPGEN("Change/remove password") : (char*)LPGEN("Set password"); }
+
+ __forceinline bool isEncrypted() const { return m_bEncrypted; }
+ __forceinline bool usesPassword() const { return m_bUsesPassword; }
+
+public:
+ STDMETHODIMP_(BOOL) IsRelational(void) { return TRUE; }
+ STDMETHODIMP_(void) SetCacheSafetyMode(BOOL);
+
+ STDMETHODIMP_(LONG) GetContactCount(void);
+ STDMETHODIMP_(LONG) DeleteContact(MCONTACT contactID);
+ STDMETHODIMP_(MCONTACT) AddContact(void);
+ STDMETHODIMP_(BOOL) IsDbContact(MCONTACT contactID);
+ STDMETHODIMP_(LONG) GetContactSize(void);
+
+ STDMETHODIMP_(LONG) GetEventCount(MCONTACT contactID);
+ STDMETHODIMP_(MEVENT) AddEvent(MCONTACT contactID, DBEVENTINFO *dbe);
+ STDMETHODIMP_(BOOL) DeleteEvent(MCONTACT contactID, MEVENT hDbEvent);
+ STDMETHODIMP_(LONG) GetBlobSize(MEVENT hDbEvent);
+ STDMETHODIMP_(BOOL) GetEvent(MEVENT hDbEvent, DBEVENTINFO *dbe);
+ STDMETHODIMP_(BOOL) MarkEventRead(MCONTACT contactID, MEVENT hDbEvent);
+ STDMETHODIMP_(MCONTACT) GetEventContact(MEVENT hDbEvent);
+ STDMETHODIMP_(MEVENT) FindFirstEvent(MCONTACT contactID);
+ STDMETHODIMP_(MEVENT) FindFirstUnreadEvent(MCONTACT contactID);
+ STDMETHODIMP_(MEVENT) FindLastEvent(MCONTACT contactID);
+ STDMETHODIMP_(MEVENT) FindNextEvent(MCONTACT contactID, MEVENT hDbEvent);
+ STDMETHODIMP_(MEVENT) FindPrevEvent(MCONTACT contactID, MEVENT hDbEvent);
+
+ STDMETHODIMP_(BOOL) EnumModuleNames(DBMODULEENUMPROC pFunc, void *pParam);
+
+ STDMETHODIMP_(BOOL) GetContactSettingWorker(MCONTACT contactID, LPCSTR szModule, LPCSTR szSetting, DBVARIANT *dbv, int isStatic);
+ STDMETHODIMP_(BOOL) WriteContactSetting(MCONTACT contactID, DBCONTACTWRITESETTING *dbcws);
+ STDMETHODIMP_(BOOL) DeleteContactSetting(MCONTACT contactID, LPCSTR szModule, LPCSTR szSetting);
+ STDMETHODIMP_(BOOL) EnumContactSettings(MCONTACT hContact, DBSETTINGENUMPROC pfnEnumProc, const char *szModule, void *param);
+
+ STDMETHODIMP_(BOOL) MetaMergeHistory(DBCachedContact *ccMeta, DBCachedContact *ccSub);
+ STDMETHODIMP_(BOOL) MetaSplitHistory(DBCachedContact *ccMeta, DBCachedContact *ccSub);
+
+public:
+ MICryptoEngine *m_crypto;
+ UINT_PTR m_timerId; // timer to flush unsaved data
+};
diff --git a/plugins/Dbx_mdbx/src/dbmodulechain.cpp b/plugins/Dbx_mdbx/src/dbmodulechain.cpp
index daaaf494ff..0ab6b3eb58 100644
--- a/plugins/Dbx_mdbx/src/dbmodulechain.cpp
+++ b/plugins/Dbx_mdbx/src/dbmodulechain.cpp
@@ -52,6 +52,7 @@ uint32_t CDbxMDBX::GetModuleID(const char *szName)
}
m_Modules[iHash] = szName;
+ DBFlush();
}
return iHash;
diff --git a/plugins/Dbx_mdbx/src/dbsettings.cpp b/plugins/Dbx_mdbx/src/dbsettings.cpp
index e8294b4b72..83211cd36f 100644
--- a/plugins/Dbx_mdbx/src/dbsettings.cpp
+++ b/plugins/Dbx_mdbx/src/dbsettings.cpp
@@ -348,6 +348,8 @@ LBL_WriteString:
// notify
lck.unlock();
+
+ DBFlush();
NotifyEventHooks(hSettingChangeEvent, contactID, (LPARAM)&dbcwNotif);
return 0;
}
@@ -381,6 +383,8 @@ STDMETHODIMP_(BOOL) CDbxMDBX::DeleteContactSetting(MCONTACT contactID, LPCSTR sz
m_cache->GetCachedValuePtr(contactID, szCachedSettingName, -1);
}
+ DBFlush();
+
// notify
DBCONTACTWRITESETTING dbcws = { 0 };
dbcws.szModule = szModule;