diff options
Diffstat (limited to 'plugins/Dbx_mdb/src/dbevents.cpp')
-rw-r--r-- | plugins/Dbx_mdb/src/dbevents.cpp | 235 |
1 files changed, 208 insertions, 27 deletions
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;
}
/////////////////////////////////////////////////////////////////////////////////////////
|