From cdf4c110510a39c162b469ecbd6f69571019cf69 Mon Sep 17 00:00:00 2001 From: George Hazan Date: Thu, 12 Apr 2018 20:55:18 +0300 Subject: initial version of profile compactor for MDBX --- include/m_db_int.h | 10 ++++- libs/win32/mir_app.lib | Bin 156592 -> 156878 bytes libs/win64/mir_app.lib | Bin 151634 -> 151924 bytes plugins/Db3x_mmap/src/init.cpp | 2 +- plugins/Dbx_mdbx/src/dbintf.cpp | 33 ++++++++++++++++ plugins/Dbx_mdbx/src/dbintf.h | 2 + plugins/Dbx_mdbx/src/init.cpp | 2 +- plugins/Dbx_mdbx/src/stdafx.h | 1 + plugins/Import/src/dbrw/dbrw.cpp | 2 +- src/mir_app/src/MDatabaseCommon.cpp | 5 +++ src/mir_app/src/mir_app.def | 1 + src/mir_app/src/mir_app64.def | 1 + src/mir_app/src/profilemanager.cpp | 76 +++++++++++++++++++++++------------- 13 files changed, 104 insertions(+), 31 deletions(-) diff --git a/include/m_db_int.h b/include/m_db_int.h index 036fc8446b..b549291385 100644 --- a/include/m_db_int.h +++ b/include/m_db_int.h @@ -125,8 +125,12 @@ interface MIR_APP_EXPORT MIDatabase STDMETHOD_(BOOL, MetaSetDefault)(DBCachedContact*) PURE; STDMETHOD_(BOOL, MetaMergeHistory)(DBCachedContact *ccMeta, DBCachedContact *ccSub) PURE; STDMETHOD_(BOOL, MetaSplitHistory)(DBCachedContact *ccMeta, DBCachedContact *ccSub) PURE; + + STDMETHOD_(BOOL, Compact)(void) PURE; }; +///////////////////////////////////////////////////////////////////////////////////////// + class MIR_APP_EXPORT MDatabaseCommon : public MIDatabase { @@ -164,6 +168,8 @@ public: STDMETHODIMP_(BOOL) EnumResidentSettings(DBMODULEENUMPROC pFunc, void *pParam); STDMETHODIMP_(BOOL) SetSettingResident(BOOL bIsResident, const char *pszSettingName); + + STDMETHODIMP_(BOOL) Compact(void); }; /////////////////////////////////////////////////////////////////////////////// @@ -184,9 +190,11 @@ public: // makeDatabase() error codes #define EMKPRF_CREATEFAILED 1 // for some reason CreateFile() didnt like something +#define MDB_CAPS_COMPACT 0x0001 // database can be compacted + struct DATABASELINK { - int cbSize; + int capabilities; char* szShortName; // uniqie short database name wchar_t* szFullName; // in English, auto-translated by the core diff --git a/libs/win32/mir_app.lib b/libs/win32/mir_app.lib index cf63f15e0c..2e610be4ea 100644 Binary files a/libs/win32/mir_app.lib and b/libs/win32/mir_app.lib differ diff --git a/libs/win64/mir_app.lib b/libs/win64/mir_app.lib index 8b650bd8c7..1c82dde576 100644 Binary files a/libs/win64/mir_app.lib and b/libs/win64/mir_app.lib differ diff --git a/plugins/Db3x_mmap/src/init.cpp b/plugins/Db3x_mmap/src/init.cpp index aea65a0ddf..587b79253b 100644 --- a/plugins/Db3x_mmap/src/init.cpp +++ b/plugins/Db3x_mmap/src/init.cpp @@ -121,7 +121,7 @@ LBL_Error: static DATABASELINK dblink = { - sizeof(DATABASELINK), + 0, "dbx_mmap", L"dbx mmap driver", makeDatabase, diff --git a/plugins/Dbx_mdbx/src/dbintf.cpp b/plugins/Dbx_mdbx/src/dbintf.cpp index 230a01920e..2c3f8907b8 100644 --- a/plugins/Dbx_mdbx/src/dbintf.cpp +++ b/plugins/Dbx_mdbx/src/dbintf.cpp @@ -167,6 +167,39 @@ int CDbxMDBX::Check(void) return (memcmp(buf, bDefHeader, _countof(bDefHeader))) ? EGROKPRF_UNKHEADER : 0; } +BOOL CDbxMDBX::Compact() +{ + CMStringW wszTmpFile(FORMAT, L"%s.tmp", m_tszProfileName); + + HANDLE pFile = ::CreateFile(wszTmpFile, GENERIC_WRITE, 0, nullptr, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, nullptr); + if (pFile == nullptr) { + Netlib_Logf(0, "Temporary file <%S> cannot be created", wszTmpFile.c_str()); + return 1; + } + + mir_cslock lck(m_csDbAccess); + int res = mdbx_env_copy2fd(m_env, pFile, MDBX_CP_COMPACT); + CloseHandle(pFile); + + if (res == MDBX_SUCCESS) { + mdbx_env_close(m_env); + + DeleteFileW(m_tszProfileName); + MoveFileW(wszTmpFile, m_tszProfileName); + + mdbx_env_create(&m_env); + mdbx_env_set_maxdbs(m_env, 10); + mdbx_env_set_maxreaders(m_env, 244); + mdbx_env_set_userctx(m_env, this); + + Map(); + Load(); + } + else DeleteFileW(wszTmpFile); + + return 0; +} + int CDbxMDBX::PrepareCheck() { InitModules(); diff --git a/plugins/Dbx_mdbx/src/dbintf.h b/plugins/Dbx_mdbx/src/dbintf.h index 0b616916ed..6d998f7d77 100644 --- a/plugins/Dbx_mdbx/src/dbintf.h +++ b/plugins/Dbx_mdbx/src/dbintf.h @@ -267,6 +267,8 @@ public: STDMETHODIMP_(BOOL) MetaMergeHistory(DBCachedContact *ccMeta, DBCachedContact *ccSub); STDMETHODIMP_(BOOL) MetaSplitHistory(DBCachedContact *ccMeta, DBCachedContact *ccSub); + STDMETHODIMP_(BOOL) Compact(); + public: MICryptoEngine *m_crypto; }; diff --git a/plugins/Dbx_mdbx/src/init.cpp b/plugins/Dbx_mdbx/src/init.cpp index 6efe170cb5..2500cd30ad 100644 --- a/plugins/Dbx_mdbx/src/init.cpp +++ b/plugins/Dbx_mdbx/src/init.cpp @@ -93,7 +93,7 @@ static MDatabaseCommon* loadDatabase(const TCHAR *profile, BOOL bReadOnly) static DATABASELINK dblink = { - sizeof(DATABASELINK), + MDB_CAPS_COMPACT, "dbx_mdbx", L"MDBX database driver", makeDatabase, diff --git a/plugins/Dbx_mdbx/src/stdafx.h b/plugins/Dbx_mdbx/src/stdafx.h index 243756e39a..5e00445dba 100644 --- a/plugins/Dbx_mdbx/src/stdafx.h +++ b/plugins/Dbx_mdbx/src/stdafx.h @@ -24,6 +24,7 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. #pragma once #include +#include #include #include diff --git a/plugins/Import/src/dbrw/dbrw.cpp b/plugins/Import/src/dbrw/dbrw.cpp index b5ed672bdb..00bf079c05 100644 --- a/plugins/Import/src/dbrw/dbrw.cpp +++ b/plugins/Import/src/dbrw/dbrw.cpp @@ -86,7 +86,7 @@ static MDatabaseCommon* dbrw_Load(const wchar_t *profile, BOOL) static DATABASELINK dblink = { - sizeof(DATABASELINK), + 0, "dbrw", L"dbx SQLite driver", dbrw_makeDatabase, diff --git a/src/mir_app/src/MDatabaseCommon.cpp b/src/mir_app/src/MDatabaseCommon.cpp index dd3034a00e..74f33688dc 100644 --- a/src/mir_app/src/MDatabaseCommon.cpp +++ b/src/mir_app/src/MDatabaseCommon.cpp @@ -82,6 +82,11 @@ BOOL MDatabaseCommon::DeleteModule(MCONTACT hContact, LPCSTR szModule) return 0; } +BOOL MDatabaseCommon::Compact(void) +{ + return ERROR_NOT_SUPPORTED; +} + ///////////////////////////////////////////////////////////////////////////////////////// // Contacts diff --git a/src/mir_app/src/mir_app.def b/src/mir_app/src/mir_app.def index d8c739b539..b449c2a281 100644 --- a/src/mir_app/src/mir_app.def +++ b/src/mir_app/src/mir_app.def @@ -580,3 +580,4 @@ Clist_GetRealStatus @599 Clist_GetGeneralizedStatus @600 Proto_GetStatus @601 ?getCache@MDatabaseCommon@@QBEPAUMIDatabaseCache@@XZ @602 NONAME +?Compact@MDatabaseCommon@@UAGHXZ @603 NONAME diff --git a/src/mir_app/src/mir_app64.def b/src/mir_app/src/mir_app64.def index 9e8b034edc..bd05a3184e 100644 --- a/src/mir_app/src/mir_app64.def +++ b/src/mir_app/src/mir_app64.def @@ -580,3 +580,4 @@ Clist_GetRealStatus @599 Clist_GetGeneralizedStatus @600 Proto_GetStatus @601 ?getCache@MDatabaseCommon@@QEBAPEAUMIDatabaseCache@@XZ @602 NONAME +?Compact@MDatabaseCommon@@UEAAHXZ @603 NONAME diff --git a/src/mir_app/src/profilemanager.cpp b/src/mir_app/src/profilemanager.cpp index de4e2b2628..a39fee2bb0 100644 --- a/src/mir_app/src/profilemanager.cpp +++ b/src/mir_app/src/profilemanager.cpp @@ -255,7 +255,7 @@ class CChooseProfileDlg : public CDlgBase if (p != nullptr) *p = 0; LVITEM item = { 0 }; - item.mask = LVIF_TEXT | LVIF_IMAGE; + item.mask = LVIF_TEXT | LVIF_IMAGE | LVIF_PARAM; item.pszText = profile; item.iItem = 0; @@ -286,6 +286,8 @@ class CChooseProfileDlg : public CDlgBase item.iImage = 3; } + item.lParam = (LPARAM)dblink; + int iItem = list.InsertItem(&item); if (mir_wstrcmpi(ped->szProfile, tszFullPath) == 0) list.SetItemState(iItem, LVIS_SELECTED | LVIS_FOCUSED, LVIS_SELECTED | LVIS_FOCUSED); @@ -303,35 +305,34 @@ class CChooseProfileDlg : public CDlgBase return TRUE; } - void DeleteProfile(int iItem) + void DeleteProfile(const LVITEM &item) { - if (iItem < 0) - return; - - wchar_t profile[MAX_PATH], profilef[MAX_PATH * 2]; - - LVITEM item = { 0 }; - item.mask = LVIF_TEXT; - item.iItem = iItem; - item.pszText = profile; - item.cchTextMax = _countof(profile); - if (!m_profileList.GetItem(&item)) - return; - - mir_snwprintf(profilef, TranslateT("Are you sure you want to remove profile \"%s\"?"), profile); - if (IDYES != MessageBox(nullptr, profilef, L"Miranda NG", MB_YESNO | MB_TASKMODAL | MB_ICONWARNING)) + CMStringW wszMessage(FORMAT, TranslateT("Are you sure you want to remove profile \"%s\"?"), item.pszText); + if (IDYES != MessageBox(nullptr, wszMessage, L"Miranda NG", MB_YESNO | MB_TASKMODAL | MB_ICONWARNING)) return; - mir_snwprintf(profilef, L"%s\\%s%c", m_pd->ptszProfileDir, profile, 0); + wszMessage.Format(L"%s\\%s%c", m_pd->ptszProfileDir, item.pszText, 0); SHFILEOPSTRUCT sf = {}; sf.wFunc = FO_DELETE; - sf.pFrom = profilef; + sf.pFrom = wszMessage; sf.fFlags = FOF_NOCONFIRMATION | FOF_SILENT | FOF_ALLOWUNDO; SHFileOperation(&sf); + m_profileList.DeleteItem(item.iItem); } + void CompactProfile(DATABASELINK *dblink, const wchar_t *profile) + { + CMStringW wszFullName(FORMAT, L"%s\\%s\\%s.dat", m_pd->ptszProfileDir, profile, profile); + + MDatabaseCommon *db = dblink->Load(wszFullName, false); + if (db != nullptr) { + db->Compact(); + delete db; + } + } + void CheckRun() { m_btnOk.Enable(m_profileList.GetSelectedCount() == 1); @@ -383,21 +384,30 @@ class CChooseProfileDlg : public CDlgBase if (lvht.iItem == -1) return; - LVITEM tvi = { 0 }; - tvi.mask = LVIF_IMAGE; - tvi.iItem = lvht.iItem; - if (!m_profileList.GetItem(&tvi)) + wchar_t profile[MAX_PATH]; + LVITEM item = { 0 }; + item.mask = LVIF_IMAGE | LVIF_PARAM | LVIF_TEXT; + item.iItem = lvht.iItem; + item.pszText = profile; + item.cchTextMax = _countof(profile); + if (!m_profileList.GetItem(&item)) return; lvht.pt.x = GET_X_LPARAM(lParam); lvht.pt.y = GET_Y_LPARAM(lParam); HMENU hMenu = CreatePopupMenu(); - if (tvi.iImage < 2) { + if (item.iImage < 2) { AppendMenu(hMenu, MF_STRING, 1, TranslateT("Run")); AppendMenu(hMenu, MF_SEPARATOR, 0, nullptr); } + DATABASELINK *dblink = (DATABASELINK*)item.lParam; + if (dblink != nullptr && dblink->capabilities & MDB_CAPS_COMPACT) { + AppendMenu(hMenu, MF_STRING, 3, TranslateT("Compact")); + AppendMenu(hMenu, MF_SEPARATOR, 0, nullptr); + } + AppendMenu(hMenu, MF_STRING, 2, TranslateT("Delete")); int index = TrackPopupMenu(hMenu, TPM_RETURNCMD, lvht.pt.x, lvht.pt.y, 0, m_hwnd, nullptr); switch (index) { @@ -406,7 +416,11 @@ class CChooseProfileDlg : public CDlgBase break; case 2: - DeleteProfile(lvht.iItem); + DeleteProfile(item); + break; + + case 3: + CompactProfile(dblink, profile); break; } DestroyMenu(hMenu); @@ -478,8 +492,16 @@ public: void list_OnKeyDown(CCtrlListView::TEventInfo *evt) { - if (evt->nmlvkey->wVKey == VK_DELETE) - DeleteProfile(m_profileList.GetNextItem(-1, LVNI_SELECTED | LVNI_ALL)); + if (evt->nmlvkey->wVKey == VK_DELETE) { + wchar_t profile[MAX_PATH]; + LVITEM item = { 0 }; + item.mask = LVIF_TEXT; + item.iItem = m_profileList.GetNextItem(-1, LVNI_SELECTED | LVNI_ALL); + item.pszText = profile; + item.cchTextMax = _countof(profile); + if (m_profileList.GetItem(&item)) + DeleteProfile(item); + } } void list_OnGetTip(CCtrlListView::TEventInfo *evt) -- cgit v1.2.3