From e829ee5d835b512517e565c6b10bc11fc4469801 Mon Sep 17 00:00:00 2001
From: George Hazan <george.hazan@gmail.com>
Date: Mon, 16 Mar 2015 22:13:15 +0000
Subject: LMDB: fix for mc split/merge

git-svn-id: http://svn.miranda-ng.org/main/trunk@12421 1316c22d-e87f-b044-9b9b-93d7a3e3ba9c
---
 plugins/Dbx_mdb/Dbx_mdb_10.vcxproj |  6 +--
 plugins/Dbx_mdb/src/dbcontacts.cpp | 79 ++++++++++++++++++++++----------------
 plugins/Dbx_mdb/src/dbintf.h       | 11 ++++++
 3 files changed, 60 insertions(+), 36 deletions(-)

(limited to 'plugins')

diff --git a/plugins/Dbx_mdb/Dbx_mdb_10.vcxproj b/plugins/Dbx_mdb/Dbx_mdb_10.vcxproj
index f976c8f631..46f00c6113 100644
--- a/plugins/Dbx_mdb/Dbx_mdb_10.vcxproj
+++ b/plugins/Dbx_mdb/Dbx_mdb_10.vcxproj
@@ -20,7 +20,7 @@
   </ItemGroup>
   <PropertyGroup Label="Globals">
     <ProjectName>Dbx_mdb</ProjectName>
-    <ProjectGuid>{E0ACDEA0-0AC9-4431-8CA3-6B0CCACB2E18}</ProjectGuid>
+    <ProjectGuid>{6D25A8AD-5251-4DAE-AA49-0E819F6A615A}</ProjectGuid>
   </PropertyGroup>
   <Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
   <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
@@ -198,10 +198,10 @@
     <ClCompile Include="src\dbmodulechain.cpp" />
     <ClCompile Include="src\dbsettings.cpp" />
     <ClCompile Include="src\lmdb\mdb.c">
-      <PrecompiledHeader >NotUsing</PrecompiledHeader>
+      <PrecompiledHeader>NotUsing</PrecompiledHeader>
     </ClCompile>
     <ClCompile Include="src\lmdb\midl.c">
-      <PrecompiledHeader >NotUsing</PrecompiledHeader>
+      <PrecompiledHeader>NotUsing</PrecompiledHeader>
     </ClCompile>
     <ClCompile Include="src\stdafx.cpp">
       <PrecompiledHeader>Create</PrecompiledHeader>
diff --git a/plugins/Dbx_mdb/src/dbcontacts.cpp b/plugins/Dbx_mdb/src/dbcontacts.cpp
index 05d235c4e3..ede6270b5f 100644
--- a/plugins/Dbx_mdb/src/dbcontacts.cpp
+++ b/plugins/Dbx_mdb/src/dbcontacts.cpp
@@ -154,31 +154,46 @@ BOOL CDbxMdb::MetaSetDefault(DBCachedContact *cc)
 
 /////////////////////////////////////////////////////////////////////////////////////////
 
-BOOL CDbxMdb::MetaMergeHistory(DBCachedContact *ccMeta, DBCachedContact *ccSub)
+void CDbxMdb::GatherContactHistory(MCONTACT hContact, LIST<EventItem> &list)
 {
-	DBEventSortingKey keyVal = { 0, 0, ccSub->contactID }, insVal = { 0, 0, ccMeta->contactID };
-	MDB_val key = { sizeof(keyVal), &keyVal }, key2 = { sizeof(insVal), &insVal }, data;
+	DBEventSortingKey keyVal = { 0, 0, hContact };
+	MDB_val key = { sizeof(keyVal), &keyVal }, data;
+
+	txn_ptr trnlck(m_pMdbEnv, true);
+	cursor_ptr cursor(trnlck, m_dbEventsSort);
+	mdb_cursor_get(cursor, &key, &data, MDB_SET);
+	while (mdb_cursor_get(cursor, &key, &data, MDB_NEXT) == MDB_SUCCESS) {
+		DBEventSortingKey *pKey = (DBEventSortingKey*)key.mv_data;
+		if (pKey->dwContactId != hContact)
+			return;
+
+		list.insert(new EventItem(pKey->ts, pKey->dwEventId));
+	}
+}
 
-	txn_ptr trnlck(m_pMdbEnv);
-	{
-		cursor_ptr cursor(trnlck, m_dbEventsSort);
-		mdb_cursor_get(cursor, &key, &data, MDB_SET);
-		while (mdb_cursor_get(cursor, &key, &data, MDB_NEXT) == MDB_SUCCESS) {
-			DBEventSortingKey *pKey = (DBEventSortingKey*)key.mv_data;
-			if (pKey->dwContactId != ccSub->contactID)
-				break;
+BOOL CDbxMdb::MetaMergeHistory(DBCachedContact *ccMeta, DBCachedContact *ccSub)
+{
+	LIST<EventItem> list(10000);
+	GatherContactHistory(ccSub->contactID, list);
 
-			insVal.ts = pKey->ts;
-			insVal.dwEventId = pKey->dwEventId;
-			mdb_put(trnlck, m_dbEventsSort, &key2, &data, 0);
+	for (int i = 0; i < list.getCount(); i++) {
+		EventItem *EI = list[i];
 
-			ccMeta->dbc.dwEventCount++;
+		for (;; Remap()) {
+			txn_ptr trnlck(m_pMdbEnv);
+			DBEventSortingKey insVal = { EI->eventId, EI->ts, ccMeta->contactID };
+			MDB_val key = { sizeof(insVal), &insVal }, data = { 1, "" };
+			mdb_put(trnlck, m_dbEventsSort, &key, &data, 0);
+			if (trnlck.commit())
+				break;
 		}
+		ccMeta->dbc.dwEventCount++;
+		delete EI;
 	}
 
 	MDB_val keyc = { sizeof(int), &ccMeta->contactID }, datac = { sizeof(ccMeta->dbc), &ccMeta->dbc };
+	txn_ptr trnlck(m_pMdbEnv);
 	mdb_put(trnlck, m_dbContacts, &keyc, &datac, 0);
-
 	trnlck.commit();
 	return 0;
 }
@@ -187,29 +202,27 @@ BOOL CDbxMdb::MetaMergeHistory(DBCachedContact *ccMeta, DBCachedContact *ccSub)
 
 BOOL CDbxMdb::MetaSplitHistory(DBCachedContact *ccMeta, DBCachedContact *ccSub)
 {
-	DBEventSortingKey keyVal = { 0, 0, ccSub->contactID }, delVal = { 0, 0, ccMeta->contactID };
-	MDB_val key = { sizeof(keyVal), &keyVal }, key2 = { sizeof(delVal), &delVal }, data;
-
-	txn_ptr trnlck(m_pMdbEnv);
-	{
-		cursor_ptr cursor(trnlck, m_dbEventsSort);
-		mdb_cursor_get(cursor, &key, &data, MDB_SET);
-		while (mdb_cursor_get(cursor, &key, &data, MDB_NEXT) == MDB_SUCCESS) {
-			DBEventSortingKey *pKey = (DBEventSortingKey*)key.mv_data;
-			if (pKey->dwContactId != ccSub->contactID)
-				break;
+	LIST<EventItem> list(10000);
+	GatherContactHistory(ccSub->contactID, list);
 
-			delVal.ts = pKey->ts;
-			delVal.dwEventId = pKey->dwEventId;
-			mdb_del(trnlck, m_dbEventsSort, &key2, &data);
+	for (int i = 0; i < list.getCount(); i++) {
+		EventItem *EI = list[i];
 
-			ccMeta->dbc.dwEventCount--;
+		for (;; Remap()) {
+			txn_ptr trnlck(m_pMdbEnv);
+			DBEventSortingKey insVal = { EI->eventId, EI->ts, ccMeta->contactID };
+			MDB_val key = { sizeof(insVal), &insVal }, data = { 1, "" };
+			mdb_del(trnlck, m_dbEventsSort, &key, &data);
+			if (trnlck.commit())
+				break;
 		}
+		ccMeta->dbc.dwEventCount--;
+		delete EI;
 	}
-	
+
 	MDB_val keyc = { sizeof(int), &ccMeta->contactID }, datac = { sizeof(ccMeta->dbc), &ccMeta->dbc };
+	txn_ptr trnlck(m_pMdbEnv);
 	mdb_put(trnlck, m_dbContacts, &keyc, &datac, 0);
-
 	trnlck.commit();
 	return 0;
 }
diff --git a/plugins/Dbx_mdb/src/dbintf.h b/plugins/Dbx_mdb/src/dbintf.h
index b97df6c787..d4b8a587a5 100644
--- a/plugins/Dbx_mdb/src/dbintf.h
+++ b/plugins/Dbx_mdb/src/dbintf.h
@@ -117,6 +117,16 @@ struct DBCachedContact : public DBCachedContactBase
 	DBContact dbc;
 };
 
+struct EventItem
+{
+	__forceinline EventItem(int _ts, DWORD _id) :
+		ts(_ts), eventId(_id)
+	{}
+
+	int ts;
+	DWORD eventId;
+};
+
 struct CDbxMdb : public MIDatabase, public MIDatabaseChecker, public MZeroedObject
 {
 	CDbxMdb(const TCHAR *tszFileName, int mode);
@@ -238,6 +248,7 @@ protected:
 	int      m_contactCount, m_dwMaxContactId;
 
 	int      WipeContactHistory(DBContact *dbc);
+	void     GatherContactHistory(MCONTACT hContact, LIST<EventItem> &items);
 
 	////////////////////////////////////////////////////////////////////////////
 	// events
-- 
cgit v1.2.3