From cdad72e9512d163ed15bc89bd0a93e7da2ee4c50 Mon Sep 17 00:00:00 2001
From: George Hazan <george.hazan@gmail.com>
Date: Sun, 18 Jan 2015 16:47:07 +0000
Subject: first working version of events

git-svn-id: http://svn.miranda-ng.org/main/trunk@11872 1316c22d-e87f-b044-9b9b-93d7a3e3ba9c
---
 plugins/Dbx_mdb/src/dbcontacts.cpp |  38 +++---
 plugins/Dbx_mdb/src/dbevents.cpp   | 235 ++++++++++++++++++++++++++++++++-----
 plugins/Dbx_mdb/src/dbintf.cpp     |  20 +++-
 plugins/Dbx_mdb/src/dbintf.h       |  41 ++-----
 plugins/Dbx_mdb/src/dbsettings.cpp |   8 +-
 5 files changed, 267 insertions(+), 75 deletions(-)

diff --git a/plugins/Dbx_mdb/src/dbcontacts.cpp b/plugins/Dbx_mdb/src/dbcontacts.cpp
index 48c8b7e7cb..cf13a782b9 100644
--- a/plugins/Dbx_mdb/src/dbcontacts.cpp
+++ b/plugins/Dbx_mdb/src/dbcontacts.cpp
@@ -171,38 +171,44 @@ BOOL CDbxMdb::MetaSplitHistory(DBCachedContact *ccMeta, DBCachedContact *ccSub)
 
 void CDbxMdb::FillContacts()
 {
-	m_contactCount = 0;
+	LIST<DBCachedContact> arContacts(10);
 
 	txn_ptr trnlck(m_pMdbEnv);
 	mdb_open(trnlck, "contacts", MDB_INTEGERKEY, &m_dbContacts);
+	{
+		cursor_ptr cursor(trnlck, m_dbContacts);
 
-	cursor_ptr cursor(trnlck, m_dbContacts);
+		MDB_val key, data;
+		while (mdb_cursor_get(cursor, &key, &data, MDB_NEXT) == 0) {
+			DBContact *dbc = (DBContact*)data.mv_data;
+			if (dbc->signature != DBCONTACT_SIGNATURE)
+				DatabaseCorruption(NULL);
 
-	MDB_val key, data;
-	while (mdb_cursor_get(cursor, &key, &data, MDB_NEXT) == 0) {
-		DBContact *dbc = (DBContact*)data.mv_data;
-		if (dbc->signature != DBCONTACT_SIGNATURE)
-			DatabaseCorruption(NULL);
+			DBCachedContact *cc = m_cache->AddContactToCache(*(DWORD*)key.mv_data);
+			cc->dwDriverData = dbc->eventCount;
+			arContacts.insert(cc);
+		}
+	}
 
-		DWORD dwContactId = *(DWORD*)key.mv_data;
-		DBCachedContact *cc = m_cache->AddContactToCache(dwContactId);
-		cc->dwDriverData = 0;
+	m_contactCount = 0;
+	for (int i = 0; i < arContacts.getCount(); i++) {
+		DBCachedContact *cc = arContacts[i];
 		CheckProto(cc, "");
-	
-		m_dwMaxContactId = dwContactId + 1;
+
+		m_dwMaxContactId = cc->contactID+1;
 		m_contactCount++;
 
 		DBVARIANT dbv; dbv.type = DBVT_DWORD;
-		cc->nSubs = (0 != GetContactSetting(dwContactId, META_PROTO, "NumContacts", &dbv)) ? -1 : dbv.dVal;
+		cc->nSubs = (0 != GetContactSetting(cc->contactID, META_PROTO, "NumContacts", &dbv)) ? -1 : dbv.dVal;
 		if (cc->nSubs != -1) {
 			cc->pSubs = (MCONTACT*)mir_alloc(cc->nSubs*sizeof(MCONTACT));
 			for (int i = 0; i < cc->nSubs; i++) {
 				char setting[100];
 				mir_snprintf(setting, SIZEOF(setting), "Handle%d", i);
-				cc->pSubs[i] = (0 != GetContactSetting(dwContactId, META_PROTO, setting, &dbv)) ? NULL : dbv.dVal;
+				cc->pSubs[i] = (0 != GetContactSetting(cc->contactID, META_PROTO, setting, &dbv)) ? NULL : dbv.dVal;
 			}
 		}
-		cc->nDefault = (0 != GetContactSetting(dwContactId, META_PROTO, "Default", &dbv)) ? -1 : dbv.dVal;
-		cc->parentID = (0 != GetContactSetting(dwContactId, META_PROTO, "ParentMeta", &dbv)) ? NULL : dbv.dVal;
+		cc->nDefault = (0 != GetContactSetting(cc->contactID, META_PROTO, "Default", &dbv)) ? -1 : dbv.dVal;
+		cc->parentID = (0 != GetContactSetting(cc->contactID, META_PROTO, "ParentMeta", &dbv)) ? NULL : dbv.dVal;
 	}
 }
diff --git a/plugins/Dbx_mdb/src/dbevents.cpp b/plugins/Dbx_mdb/src/dbevents.cpp
index ae5344ae4e..5db1d6714b 100644
--- a/plugins/Dbx_mdb/src/dbevents.cpp
+++ b/plugins/Dbx_mdb/src/dbevents.cpp
@@ -23,10 +23,19 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
 
 #include "commonheaders.h"
 
+struct DBEventSortingKey
+{
+	DWORD dwContactId, ts, dwEventId;
+};
+
 STDMETHODIMP_(LONG) CDbxMdb::GetEventCount(MCONTACT contactID)
 {
 	mir_cslock lck(m_csDbAccess);
-	return -1;
+	if (contactID == NULL)
+		return m_header.eventCount;
+
+	DBCachedContact *cc = m_cache->GetCachedContact(contactID);
+	return (cc == NULL) ? 0 : cc->dwDriverData;
 }
 
 STDMETHODIMP_(MEVENT) CDbxMdb::AddEvent(MCONTACT contactID, DBEVENTINFO *dbei)
@@ -37,6 +46,7 @@ STDMETHODIMP_(MEVENT) CDbxMdb::AddEvent(MCONTACT contactID, DBEVENTINFO *dbei)
 	DBEvent dbe;
 	dbe.signature = DBEVENT_SIGNATURE;
 	dbe.contactID = contactID; // store native or subcontact's id
+	dbe.ofsModuleName = GetModuleNameOfs(dbei->szModule);
 	dbe.timestamp = dbei->timestamp;
 	dbe.flags = dbei->flags;
 	dbe.wEventType = dbei->eventType;
@@ -44,11 +54,10 @@ STDMETHODIMP_(MEVENT) CDbxMdb::AddEvent(MCONTACT contactID, DBEVENTINFO *dbei)
 	BYTE *pBlob = dbei->pBlob;
 
 	MCONTACT contactNotifyID = contactID;
-	DBCachedContact *ccSub = NULL;
+	DBCachedContact *cc = NULL, *ccSub = NULL;
 	if (contactID != 0) {
-		DBCachedContact *cc = m_cache->GetCachedContact(contactID);
-		if (cc == NULL)
-			return NULL;
+		if ((cc = m_cache->GetCachedContact(contactID)) == NULL)
+			return 0;
 
 		if (cc->IsSub()) {
 			ccSub = cc;
@@ -76,32 +85,92 @@ STDMETHODIMP_(MEVENT) CDbxMdb::AddEvent(MCONTACT contactID, DBEVENTINFO *dbei)
 	}
 
 	mir_cslockfull lck(m_csDbAccess);
+	DWORD dwEventId = (contactID == NULL) ? ++m_header.eventCount : ++m_dwMaxEventId;
+
+	txn_ptr txn(m_pMdbEnv);
+
+	for (;; Remap()) {
+		MDB_val key = { sizeof(int), &dwEventId }, data = { sizeof(DBEvent) + dbe.cbBlob, NULL };
+		if (mdb_put(txn, m_dbEvents, &key, &data, MDB_RESERVE) != MDB_SUCCESS)
+			return 0;
+
+		BYTE *pDest = (BYTE*)data.mv_data;
+		memcpy(pDest, &dbe, sizeof(DBEvent));
+		memcpy(pDest + sizeof(DBEvent), pBlob, dbe.cbBlob);
+
+		// add a sorting key
+		DBEventSortingKey key2 = { contactID, dbe.timestamp, dwEventId };
+		key.mv_size = sizeof(key2); key.mv_data = &key2;
+		data.mv_size = 1; data.mv_data = "";
+		if (mdb_put(txn, m_dbEventsSort, &key, &data, 0) != MDB_SUCCESS)
+			return 0;
+
+		if (contactID != NULL) {
+			DBContact dbc = { DBCONTACT_SIGNATURE, ++cc->dwDriverData };
+			MDB_val keyc = { sizeof(int), &contactID }, datac = { sizeof(DBContact), &dbc };
+			mdb_put(txn, m_dbContacts, &keyc, &datac, 0);
+
+			// insert an event into a sub's history too
+			if (ccSub != NULL) {
+				key2.dwContactId = ccSub->contactID;
+				mdb_put(txn, m_dbEventsSort, &key, &data, 0);
+
+				dbc.eventCount = ++ccSub->dwDriverData;
+				keyc.mv_data = &ccSub->contactID;
+				mdb_put(txn, m_dbContacts, &keyc, &datac, 0);
+			}
+		}
+		else {
+			DWORD keyVal = 1;
+			MDB_val key = { sizeof(DWORD), &keyVal };
+			data.mv_data = &m_header; data.mv_size = sizeof(m_header);
+			mdb_put(txn, m_dbGlobal, &key, &data, 0);
+		}
+
+		if (txn.commit())
+			break;
+	}
 
 	lck.unlock();
 
 	// Notify only in safe mode or on really new events
-	NotifyEventHooks(hEventAddedEvent, contactNotifyID, (LPARAM)-1);
+	NotifyEventHooks(hEventAddedEvent, contactNotifyID, dwEventId);
 
-	return (MEVENT)0;
+	return dwEventId;
 }
 
 STDMETHODIMP_(BOOL) CDbxMdb::DeleteEvent(MCONTACT contactID, MEVENT hDbEvent)
 {
-	DBCachedContact *cc;
-	if (contactID) {
-		if ((cc = m_cache->GetCachedContact(contactID)) == NULL)
-			return 2;
-		if (cc->IsSub())
-			if ((cc = m_cache->GetCachedContact(cc->parentID)) == NULL)
-				return 3;
-	}
-	else cc = NULL;
-
 	mir_cslockfull lck(m_csDbAccess);
+	txn_ptr txn(m_pMdbEnv);
+
+	for (;; Remap()) {
+		MDB_val key = { sizeof(MEVENT), &hDbEvent }, data;
+		if (mdb_get(txn, m_dbEvents, &key, &data) != MDB_SUCCESS)
+			return 1;
+
+		DBEvent *dbe = (DBEvent*)data.mv_data;
+		DWORD dwSavedContact = dbe->contactID;
+		DBEventSortingKey key2 = { contactID, dbe->timestamp, hDbEvent };
+		mdb_del(txn, m_dbEvents, &key, &data);
+
+		// remove a sorting key
+		key.mv_size = sizeof(key2); key.mv_data = &key2;
+		mdb_del(txn, m_dbEventsSort, &key, &data);
+
+		// remove a sub's history entry too
+		if (contactID != dwSavedContact) {
+			key2.dwContactId = dwSavedContact;
+			mdb_del(txn, m_dbEventsSort, &key, &data);
+		}
+
+		if (txn.commit())
+			break;
+	}
 	lck.unlock();
 
 	// call notifier while outside mutex
-	NotifyEventHooks(hEventDeletedEvent, contactID, (LPARAM)hDbEvent);
+	NotifyEventHooks(hEventDeletedEvent, contactID, hDbEvent);
 
 	// get back in
 	lck.lock();
@@ -111,7 +180,14 @@ STDMETHODIMP_(BOOL) CDbxMdb::DeleteEvent(MCONTACT contactID, MEVENT hDbEvent)
 STDMETHODIMP_(LONG) CDbxMdb::GetBlobSize(MEVENT hDbEvent)
 {
 	mir_cslock lck(m_csDbAccess);
-	return -1;
+	txn_ptr txn(m_pMdbEnv, true);
+
+	MDB_val key = { sizeof(MEVENT), &hDbEvent }, data;
+	if (mdb_get(txn, m_dbEvents, &key, &data) != MDB_SUCCESS)
+		return 0;
+
+	DBEvent *dbe = (DBEvent*)data.mv_data;
+	return (dbe->signature == DBEVENT_SIGNATURE) ? dbe->cbBlob : 0;
 }
 
 STDMETHODIMP_(BOOL) CDbxMdb::GetEvent(MEVENT hDbEvent, DBEVENTINFO *dbei)
@@ -123,6 +199,38 @@ STDMETHODIMP_(BOOL) CDbxMdb::GetEvent(MEVENT hDbEvent, DBEVENTINFO *dbei)
 	}
 
 	mir_cslock lck(m_csDbAccess);
+	txn_ptr txn(m_pMdbEnv, true);
+
+	MDB_val key = { sizeof(MEVENT), &hDbEvent }, data;
+	if (mdb_get(txn, m_dbEvents, &key, &data) != MDB_SUCCESS)
+		return 1;
+
+	DBEvent *dbe = (DBEvent*)data.mv_data;
+	if (dbe->signature != DBEVENT_SIGNATURE)
+		return 1;
+
+	dbei->szModule = GetModuleNameByOfs(dbe->ofsModuleName);
+	dbei->timestamp = dbe->timestamp;
+	dbei->flags = dbe->flags;
+	dbei->eventType = dbe->wEventType;
+	int bytesToCopy = (dbei->cbBlob < dbe->cbBlob) ? dbei->cbBlob : dbe->cbBlob;
+	dbei->cbBlob = dbe->cbBlob;
+	if (bytesToCopy && dbei->pBlob) {
+		BYTE *pSrc = (BYTE*)data.mv_data + sizeof(DBEvent);
+		if (dbe->flags & DBEF_ENCRYPTED) {
+			dbei->flags &= ~DBEF_ENCRYPTED;
+			size_t len;
+			BYTE* pBlob = (BYTE*)m_crypto->decodeBuffer(pSrc, dbe->cbBlob, &len);
+			if (pBlob == NULL)
+				return 1;
+
+			memcpy(dbei->pBlob, pBlob, bytesToCopy);
+			if (bytesToCopy > (int)len)
+				memset(dbei->pBlob + len, 0, bytesToCopy - len);
+			mir_free(pBlob);
+		}
+		else memcpy(dbei->pBlob, pSrc, bytesToCopy);
+	}
 	return 0;
 }
 
@@ -139,22 +247,55 @@ STDMETHODIMP_(BOOL) CDbxMdb::MarkEventRead(MCONTACT contactID, MEVENT hDbEvent)
 	else cc = NULL;
 
 	mir_cslockfull lck(m_csDbAccess);
+	txn_ptr txn(m_pMdbEnv);
+
+	MDB_val key = { sizeof(MEVENT), &hDbEvent }, data;
+	if (mdb_get(txn, m_dbEvents, &key, &data) != MDB_SUCCESS)
+		return 0;
+
+	DBEvent *dbe = (DBEvent*)data.mv_data;
+	if (dbe->signature != DBEVENT_SIGNATURE)
+		return -1;
+
+	if (dbe->markedRead())
+		return dbe->flags;
+
+	dbe->flags |= DBEF_READ;
+	mdb_put(txn, m_dbEvents, &key, &data, 0);
+	txn.commit();
 
 	lck.unlock();
 	NotifyEventHooks(hEventMarkedRead, contactID, (LPARAM)hDbEvent);
-	return -11;
+	return dbe->flags;
 }
 
 STDMETHODIMP_(MCONTACT) CDbxMdb::GetEventContact(MEVENT hDbEvent)
 {
 	mir_cslock lck(m_csDbAccess);
-	return INVALID_CONTACT_ID;
+	txn_ptr txn(m_pMdbEnv, true);
+
+	MDB_val key = { sizeof(MEVENT), &hDbEvent }, data;
+	if (mdb_get(txn, m_dbEvents, &key, &data) != MDB_SUCCESS)
+		return 0;
+
+	DBEvent *dbe = (DBEvent*)data.mv_data;
+	return (dbe->signature == DBEVENT_SIGNATURE) ? dbe->contactID: INVALID_CONTACT_ID;
 }
 
 STDMETHODIMP_(MEVENT) CDbxMdb::FindFirstEvent(MCONTACT contactID)
 {
+	DBEventSortingKey keyVal = { contactID, 0, 0 };
+	MDB_val key = { sizeof(keyVal), &keyVal }, data;
+
 	mir_cslock lck(m_csDbAccess);
-	return NULL;
+	txn_ptr txn(m_pMdbEnv, true);
+
+	cursor_ptr cursor(txn, m_dbEventsSort);
+	if (mdb_cursor_get(cursor, &key, &data, MDB_NEXT) != MDB_SUCCESS)
+		return 0;
+
+	DBEventSortingKey *pKey = (DBEventSortingKey*)key.mv_data;
+	return (pKey->dwContactId == contactID) ? pKey->dwEventId : 0;		
 }
 
 STDMETHODIMP_(MEVENT) CDbxMdb::FindFirstUnreadEvent(MCONTACT contactID)
@@ -165,24 +306,64 @@ STDMETHODIMP_(MEVENT) CDbxMdb::FindFirstUnreadEvent(MCONTACT contactID)
 
 STDMETHODIMP_(MEVENT) CDbxMdb::FindLastEvent(MCONTACT contactID)
 {
+	DBEventSortingKey keyVal = { contactID, 0, 0 };
+	MDB_val key = { sizeof(keyVal), &keyVal }, data;
+
 	mir_cslock lck(m_csDbAccess);
-	return NULL;
+	txn_ptr txn(m_pMdbEnv, true);
+	
+	cursor_ptr cursor(txn, m_dbEventsSort);
+	if (mdb_cursor_get(cursor, &key, &data, MDB_PREV) != MDB_SUCCESS)
+		return 0;
+
+	DBEventSortingKey *pKey = (DBEventSortingKey*)key.mv_data;
+	return (pKey->dwContactId == contactID) ? pKey->dwEventId : 0;
 }
 
 STDMETHODIMP_(MEVENT) CDbxMdb::FindNextEvent(MCONTACT contactID, MEVENT hDbEvent)
 {
-	DBCachedContact *cc = (contactID) ? m_cache->GetCachedContact(contactID) : NULL;
+	MDB_val key = { sizeof(MEVENT), &hDbEvent }, data;
 
 	mir_cslock lck(m_csDbAccess);
-	return NULL;
+	txn_ptr txn(m_pMdbEnv, true);
+	
+	if (mdb_get(txn, m_dbEvents, &key, &data) != MDB_SUCCESS)
+		return 0;
+
+	DBEvent *dbe = (DBEvent*)data.mv_data;
+	DBEventSortingKey keyVal = { contactID, dbe->timestamp, hDbEvent+1 };
+	key.mv_size = sizeof(keyVal); key.mv_data = &keyVal;
+
+	cursor_ptr cursor(txn, m_dbEventsSort);
+	if (mdb_cursor_get(cursor, &key, &data, MDB_SET_KEY) != MDB_SUCCESS)
+		if (mdb_cursor_get(cursor, &key, &data, MDB_NEXT) != MDB_SUCCESS)
+			return 0;
+
+	DBEventSortingKey *pKey = (DBEventSortingKey*)key.mv_data;
+	return (pKey->dwContactId == contactID) ? pKey->dwEventId : 0;
 }
 
 STDMETHODIMP_(MEVENT) CDbxMdb::FindPrevEvent(MCONTACT contactID, MEVENT hDbEvent)
 {
-	DBCachedContact *cc = (contactID) ? m_cache->GetCachedContact(contactID) : NULL;
+	MDB_val key = { sizeof(MEVENT), &hDbEvent }, data;
 
 	mir_cslock lck(m_csDbAccess);
-	return NULL;
+	txn_ptr txn(m_pMdbEnv, true);
+
+	if (mdb_get(txn, m_dbEvents, &key, &data) != MDB_SUCCESS)
+		return 0;
+
+	DBEvent *dbe = (DBEvent*)data.mv_data;
+	DBEventSortingKey keyVal = { contactID, dbe->timestamp, hDbEvent - 1 };
+	key.mv_size = sizeof(keyVal); key.mv_data = &keyVal;
+
+	cursor_ptr cursor(txn, m_dbEventsSort);
+	if (mdb_cursor_get(cursor, &key, &data, MDB_SET_KEY) != MDB_SUCCESS)
+		if (mdb_cursor_get(cursor, &key, &data, MDB_PREV) != MDB_SUCCESS)
+			return 0;
+
+	DBEventSortingKey *pKey = (DBEventSortingKey*)key.mv_data;
+	return (pKey->dwContactId == contactID) ? pKey->dwEventId : 0;
 }
 
 /////////////////////////////////////////////////////////////////////////////////////////
diff --git a/plugins/Dbx_mdb/src/dbintf.cpp b/plugins/Dbx_mdb/src/dbintf.cpp
index f519d3dd4b..01bbfe4fed 100644
--- a/plugins/Dbx_mdb/src/dbintf.cpp
+++ b/plugins/Dbx_mdb/src/dbintf.cpp
@@ -90,11 +90,29 @@ int CDbxMdb::Load(bool bSkipInit)
 
 	if (!bSkipInit) {
 		txn_ptr trnlck(m_pMdbEnv);
+		mdb_open(trnlck, "global", MDB_CREATE | MDB_INTEGERKEY, &m_dbGlobal);
 		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, "eventsrt", MDB_CREATE, &m_dbEvents);
+		mdb_open(trnlck, "eventsrt", MDB_CREATE | MDB_INTEGERKEY, &m_dbEventsSort);
 		mdb_open(trnlck, "settings", MDB_CREATE, &m_dbSettings);
+
+		DWORD keyVal = 1;
+		MDB_val key = { sizeof(DWORD), &keyVal }, data;
+		if (mdb_get(trnlck, m_dbGlobal, &key, &data) == MDB_SUCCESS) {
+			DBHeader *hdr = (DBHeader*)data.mv_data;
+			if (hdr->signature != DBHEADER_SIGNATURE)
+				DatabaseCorruption(NULL);
+
+			memcpy(&m_header, data.mv_data, sizeof(m_header));
+		}
+		else {
+			m_header.signature = DBHEADER_SIGNATURE;
+			m_header.dwVersion = 1;
+			m_header.eventCount = 0;
+			data.mv_data = &m_header; data.mv_size = sizeof(m_header);
+			mdb_put(trnlck, m_dbGlobal, &key, &data, 0);
+		}
 		trnlck.commit();
 
 		if (InitModuleNames()) return EGROKPRF_CANTREAD;
diff --git a/plugins/Dbx_mdb/src/dbintf.h b/plugins/Dbx_mdb/src/dbintf.h
index 26f7c29629..cf9600eadf 100644
--- a/plugins/Dbx_mdb/src/dbintf.h
+++ b/plugins/Dbx_mdb/src/dbintf.h
@@ -47,31 +47,11 @@ DBHeader
 #define DBMODE_SHARED    0x0001
 #define DBMODE_READONLY  0x0002
 
-#define DB_OLD_VERSION   0x00000700u
-#define DB_094_VERSION   0x00000701u
-#define DB_095_VERSION   0x00000800u
-#define DB_095_1_VERSION 0x00000801u
-
-#define DB_SETTINGS_RESIZE_GRANULARITY  128
-
-#define WSOFS_END   0xFFFFFFFF
-#define WS_ERROR    0xFFFFFFFF
-
 #define DBVT_ENCRYPTED   250
 #define DBVT_UNENCRYPTED 251
 
 #define MARKED_READ (DBEF_READ | DBEF_SENT)
 
-#define NeedBytes(n)   if (bytesRemaining<(n)) pBlob = (PBYTE)DBRead(ofsBlobPtr,&bytesRemaining)
-#define MoveAlong(n)   {int x = n; pBlob += (x); ofsBlobPtr += (x); bytesRemaining -= (x);}
-
-DWORD __forceinline GetSettingValueLength(PBYTE pSetting)
-{
-	if (pSetting[0] & DBVTF_VARIABLELENGTH)
-		return 2 + *(PWORD)(pSetting + 1);
-	return pSetting[0];
-}
-
 struct ModuleName
 {
 	char *name;
@@ -80,21 +60,22 @@ struct ModuleName
 
 #include <pshpack1.h>
 
-struct DBSettingKey
+#define DBHEADER_SIGNATURE  0x40DECADEu
+struct DBHeader
 {
-	DWORD dwContactID;
-	DWORD dwOfsModule;
-	char  szSettingName[100];
+	DWORD signature;
+	DWORD dwVersion;			// database format version
+	DWORD eventCount;       // number of events in the chain for this contact
 };
 
-#define DBCONTACT_SIGNATURE   0x43DECADEu
+#define DBCONTACT_SIGNATURE 0x43DECADEu
 struct DBContact
 {
 	DWORD signature;
 	DWORD eventCount;       // number of events in the chain for this contact
 };
 
-#define DBMODULENAME_SIGNATURE  0x4DDECADEu
+#define DBMODULENAME_SIGNATURE 0x4DDECADEu
 struct DBModuleName
 {
 	DWORD signature;
@@ -111,8 +92,7 @@ struct DBEvent
 	DWORD timestamp;        // seconds since 00:00:00 01/01/1970
 	DWORD flags;            // see m_database.h, db/event/add
 	WORD  wEventType;       // module-defined event type
-	DWORD cbBlob;           // number of bytes in the blob
-	BYTE  blob[1];          // the blob. module-defined formatting
+	WORD  cbBlob;           // number of bytes in the blob
 
 	bool __forceinline markedRead() const
 	{
@@ -219,6 +199,8 @@ public:
 protected:
 	MDB_env *m_pMdbEnv;
 	DWORD    m_dwFileSize;
+	MDB_dbi  m_dbGlobal;
+	DBHeader m_header;
 
 	HANDLE   hSettingChangeEvent, hContactDeletedEvent, hContactAddedEvent, hEventMarkedRead;
 
@@ -244,7 +226,8 @@ protected:
 	////////////////////////////////////////////////////////////////////////////
 	// events
 
-	MDB_dbi	m_dbEvents;
+	MDB_dbi	m_dbEvents, m_dbEventsSort;
+	DWORD    m_dwMaxEventId;
 
 	////////////////////////////////////////////////////////////////////////////
 	// modules
diff --git a/plugins/Dbx_mdb/src/dbsettings.cpp b/plugins/Dbx_mdb/src/dbsettings.cpp
index f8b307936f..2955466c50 100644
--- a/plugins/Dbx_mdb/src/dbsettings.cpp
+++ b/plugins/Dbx_mdb/src/dbsettings.cpp
@@ -23,8 +23,12 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
 
 #include "commonheaders.h"
 
-DWORD GetModuleNameOfs(const char *szName);
-DBCachedContact* AddToCachedContactList(MCONTACT contactID, int index);
+struct DBSettingKey
+{
+	DWORD dwContactID;
+	DWORD dwOfsModule;
+	char  szSettingName[100];
+};
 
 #define VLT(n) ((n == DBVT_UTF8 || n == DBVT_ENCRYPTED)?DBVT_ASCIIZ:n)
 
-- 
cgit v1.2.3