예제 #1
0
STDMETHODIMP_(BOOL) CDb3Mmap::MarkEventRead(MCONTACT contactID, HANDLE hDbEvent)
{
	DBCachedContact *cc;
	if (contactID) {
		if ((cc = m_cache->GetCachedContact(contactID)) == NULL)
			return -1;
		if (cc->IsSub())
			if ((cc = m_cache->GetCachedContact(cc->parentID)) == NULL)
				return -1;
	}
	else cc = NULL;

	mir_cslockfull lck(m_csDbAccess);
	DWORD ofsContact = (cc) ? cc->dwDriverData : m_dbHeader.ofsUser;
	DBContact dbc = *(DBContact*)DBRead(ofsContact, sizeof(DBContact), NULL);
	DBEvent *dbe = (DBEvent*)DBRead((DWORD)hDbEvent, sizeof(DBEvent), NULL);
	if (dbe->signature != DBEVENT_SIGNATURE || dbc.signature != DBCONTACT_SIGNATURE)
		return -1;

	if (dbe->markedRead())
		return dbe->flags;

	// log1("mark read @ %08x", hContact);
	dbe->flags |= DBEF_READ;
	DBWrite((DWORD)hDbEvent, dbe, sizeof(DBEvent));
	BOOL ret = dbe->flags;
	if (dbc.ofsFirstUnread == (DWORD)hDbEvent) {
		for (;;) {
			if (dbe->ofsNext == 0) {
				dbc.ofsFirstUnread = 0;
				dbc.tsFirstUnread = 0;
				break;
			}
			DWORD ofsThis = dbe->ofsNext;
			dbe = (DBEvent*)DBRead(ofsThis, sizeof(DBEvent), NULL);
			if (!dbe->markedRead()) {
				dbc.ofsFirstUnread = ofsThis;
				dbc.tsFirstUnread = dbe->timestamp;
				break;
			}
		}
	}
	DBWrite(ofsContact, &dbc, sizeof(DBContact));
	DBFlush(0);
	
	lck.unlock();
	NotifyEventHooks(hEventMarkedRead, contactID, (LPARAM)hDbEvent);
	return ret;
}
예제 #2
0
STDMETHODIMP_(BOOL) CDbxKyoto::MarkEventRead(MCONTACT contactID, MEVENT hDbEvent)
{
	if (hDbEvent == 0) return -1;

	DBCachedContact *cc = m_cache->GetCachedContact(contactID);
	if (cc == NULL)
		return -1;

	mir_cslock lck(m_csDbAccess);
	VisitorCopyRec visitor;
	if (!m_dbEvents.accept((LPCSTR)&hDbEvent, sizeof(MEVENT), &visitor, false))
		return -1;

	DBEvent *dbe = (DBEvent*)visitor.vbuf_;
	if (dbe->dwSignature != DBEVENT_SIGNATURE)
		return -1;

	if (dbe->markedRead())
		return dbe->flags;

	DBEventSortingKey key2 = { contactID, dbe->timestamp, hDbEvent };

	dbe->flags |= DBEF_READ;
	m_dbEvents.set((LPCSTR)&hDbEvent, sizeof(MEVENT), visitor.vbuf_, visitor.vsiz_);

	FindNextUnread(cc, key2);
	m_dbContacts.set((LPCSTR)&contactID, sizeof(int), (LPCSTR)&cc->dbc, sizeof(cc->dbc));

	NotifyEventHooks(hEventMarkedRead, contactID, (LPARAM)hDbEvent);
	return dbe->flags;
}
예제 #3
0
STDMETHODIMP_(HANDLE) CDb3Mmap::FindFirstUnreadEvent(MCONTACT contactID)
{
	DBCachedContact *cc;
	DWORD ofsContact = GetContactOffset(contactID, &cc);

	mir_cslock lck(m_csDbAccess);
	DBContact *dbc = (DBContact*)DBRead(ofsContact, sizeof(DBContact), NULL);
	if (dbc->signature != DBCONTACT_SIGNATURE)
		return NULL;
	if (!cc || !cc->IsSub())
		return HANDLE(dbc->ofsFirstUnread);

	if ((cc = m_cache->GetCachedContact(cc->parentID)) == NULL)
		return NULL;
	dbc = (DBContact*)DBRead(cc->dwDriverData, sizeof(DBContact), NULL);
	if (dbc->signature != DBCONTACT_SIGNATURE)
		return NULL;

	for (DWORD dwOffset = dbc->ofsFirstUnread; dwOffset != 0;) {
		DBEvent *dbe = (DBEvent*)DBRead(dwOffset, sizeof(DBEvent), NULL);
		if (dbe->signature != DBEVENT_SIGNATURE)
			return NULL;
		if (dbe->contactID == contactID && !dbe->markedRead())
			return HANDLE(dwOffset);
		dwOffset = dbe->ofsNext;
	}
	return NULL;
}
예제 #4
0
STDMETHODIMP_(MEVENT) CDb3Mmap::FindFirstUnreadEvent(MCONTACT contactID)
{
	DBCachedContact *cc;
	DWORD ofsContact = GetContactOffset(contactID, &cc);

	mir_cslock lck(m_csDbAccess);
	DBContact *dbc = (DBContact*)DBRead(ofsContact, nullptr);
	if (dbc->signature != DBCONTACT_SIGNATURE)
		return 0;
	if (!cc || !cc->IsSub())
		return MEVENT(dbc->ofsFirstUnread);

	if ((cc = m_cache->GetCachedContact(cc->parentID)) == nullptr)
		return 0;
	dbc = (DBContact*)DBRead(cc->dwOfsContact, nullptr);
	if (dbc->signature != DBCONTACT_SIGNATURE)
		return 0;

	for (DWORD dwOffset = dbc->ofsFirstUnread; dwOffset != 0;) {
		DBEvent *dbe = AdaptEvent(dwOffset, contactID);
		if (dbe->signature != DBEVENT_SIGNATURE)
			return 0;
		if (dbe->contactID == contactID && !dbe->markedRead())
			return MEVENT(dwOffset);
		dwOffset = dbe->ofsNext;
	}
	return 0;
}
예제 #5
0
void CDbxKyoto::FindNextUnread(DBCachedContact *cc, DBEventSortingKey &key2)
{
	key2.dwEventId++;
	{
		mir_cslock lck(m_csDbAccess);

		m_evCursor->jump((LPCSTR)&key2, sizeof(key2));
		while (m_evCursor->step()) {
			size_t size;
			const char *pRec;
			delete[] m_evCursor->get(&size, &pRec, &size);
			DBEvent *dbe = (DBEvent*)pRec;
			if (!dbe->markedRead()) {
				cc->dbc.dwFirstUnread = key2.dwEventId;
				cc->dbc.tsFirstUnread = key2.ts;
				return;
			}
		}
	}

	cc->dbc.dwFirstUnread = cc->dbc.tsFirstUnread = 0;
}
예제 #6
0
STDMETHODIMP_(BOOL) CDb3Mmap::DeleteEvent(MCONTACT contactID, HANDLE 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);
	DWORD ofsContact = (cc) ? cc->dwDriverData : m_dbHeader.ofsUser;
	DBContact dbc = *(DBContact*)DBRead(ofsContact, sizeof(DBContact), NULL);
	DBEvent dbe = *(DBEvent*)DBRead((DWORD)hDbEvent, sizeof(DBEvent), NULL);
	if (dbc.signature != DBCONTACT_SIGNATURE || dbe.signature != DBEVENT_SIGNATURE)
		return 1;

	lck.unlock();
	log1("delete event @ %08x", hContact);

	// call notifier while outside mutex
	NotifyEventHooks(hEventDeletedEvent, contactID, (LPARAM)hDbEvent);

	// get back in
	lck.lock();
	dbc = *(DBContact*)DBRead(ofsContact, sizeof(DBContact), NULL);
	dbe = *(DBEvent*)DBRead((DWORD)hDbEvent, sizeof(DBEvent), NULL);

	// check if this was the first unread, if so, recalc the first unread
	if (dbc.ofsFirstUnread == (DWORD)hDbEvent) {
		for (DBEvent *dbeNext = &dbe;;) {
			if (dbeNext->ofsNext == 0) {
				dbc.ofsFirstUnread = 0;
				dbc.tsFirstUnread = 0;
				break;
			}
			DWORD ofsThis = dbeNext->ofsNext;
			dbeNext = (DBEvent*)DBRead(ofsThis, sizeof(DBEvent), NULL);
			if (!dbeNext->markedRead()) {
				dbc.ofsFirstUnread = ofsThis;
				dbc.tsFirstUnread = dbeNext->timestamp;
				break;
			}
		}
	}

	// get previous and next events in chain and change offsets
	if (dbe.ofsPrev == 0) {
		if (dbe.ofsNext == 0)
			dbc.ofsFirstEvent = dbc.ofsLastEvent = 0;
		else {
			DBEvent *dbeNext = (DBEvent*)DBRead(dbe.ofsNext, sizeof(DBEvent), NULL);
			dbeNext->ofsPrev = 0;
			DBWrite(dbe.ofsNext, dbeNext, sizeof(DBEvent));
			dbc.ofsFirstEvent = dbe.ofsNext;
		}
	}
	else {
		if (dbe.ofsNext == 0) {
			DBEvent *dbePrev = (DBEvent*)DBRead(dbe.ofsPrev, sizeof(DBEvent), NULL);
			dbePrev->ofsNext = 0;
			DBWrite(dbe.ofsPrev, dbePrev, sizeof(DBEvent));
			dbc.ofsLastEvent = dbe.ofsPrev;
		}
		else {
			DBEvent *dbePrev = (DBEvent*)DBRead(dbe.ofsPrev, sizeof(DBEvent), NULL);
			dbePrev->ofsNext = dbe.ofsNext;
			DBWrite(dbe.ofsPrev, dbePrev, sizeof(DBEvent));

			DBEvent *dbeNext = (DBEvent*)DBRead(dbe.ofsNext, sizeof(DBEvent), NULL);
			dbeNext->ofsPrev = dbe.ofsPrev;
			DBWrite(dbe.ofsNext, dbeNext, sizeof(DBEvent));
		}
	}

	// decrement event count
	dbc.eventCount--;
	DBWrite(ofsContact, &dbc, sizeof(DBContact));

	// delete event
	DeleteSpace((DWORD)hDbEvent, offsetof(DBEvent, blob) + dbe.cbBlob);

	// also update a sub
	if (cc && dbe.contactID != cc->contactID) {
		DBContact *pSub = (DBContact*)DBRead(GetContactOffset(dbe.contactID), sizeof(DBContact), NULL);
		if (pSub->eventCount > 0)
			pSub->eventCount--;
	}

	DBFlush(0);
	return 0;
}
예제 #7
0
BOOL CDb3Mmap::MetaSplitHistory(DBCachedContact *ccMeta, DBCachedContact *ccSub)
{
	mir_cslock lck(m_csDbAccess);
	DBContact dbMeta = *(DBContact*)DBRead(ccMeta->dwDriverData, NULL);
	DBContact dbSub = *(DBContact*)DBRead(ccSub->dwDriverData, NULL);
	if (dbMeta.signature != DBCONTACT_SIGNATURE || dbSub.signature != DBCONTACT_SIGNATURE)
		return 1;

	if (dbMeta.ofsFirstEvent == 0) // nothing to do
		return 0;

	BOOL ret = 0;
	__try {
		if (ret = WipeContactHistory(&dbSub))
			__leave;

		DWORD dwOffset = dbMeta.ofsFirstEvent;
		DBEvent *evMeta = NULL, *evSub = NULL;
		dbMeta.eventCount = 0; dbMeta.ofsFirstEvent = dbMeta.ofsLastEvent = dbMeta.ofsFirstUnread = dbMeta.tsFirstUnread = 0;

		while (dwOffset != 0) {
			DBEvent *evCurr = (DBEvent*)DBRead(dwOffset, NULL);
			if (evCurr->signature != DBEVENT_SIGNATURE)
				break;

			DWORD dwNext = evCurr->ofsNext; evCurr->ofsNext = 0;

			// extract it to sub's chain
			if (evCurr->contactID == ccSub->contactID) {
				dbSub.eventCount++;
				if (evSub != NULL) {
					evSub->ofsNext = dwOffset;
					evCurr->ofsPrev = DWORD(PBYTE(evSub) - m_pDbCache);
				}
				else {
					dbSub.ofsFirstEvent = dwOffset;
					evCurr->ofsPrev = 0;
				}
				if (dbSub.ofsFirstUnread == 0 && !evCurr->markedRead()) {
					dbSub.ofsFirstUnread = dwOffset;
					dbSub.tsFirstUnread = evCurr->timestamp;
				}
				dbSub.ofsLastEvent = dwOffset;
				evSub = evCurr;
			}
			else {
				dbMeta.eventCount++;
				if (evMeta != NULL) {
					evMeta->ofsNext = dwOffset;
					evCurr->ofsPrev = DWORD(PBYTE(evMeta) - m_pDbCache);
				}
				else {
					dbMeta.ofsFirstEvent = dwOffset;
					evCurr->ofsPrev = 0;
				}
				if (dbMeta.ofsFirstUnread == 0 && !evCurr->markedRead()) {
					dbMeta.ofsFirstUnread = dwOffset;
					dbMeta.tsFirstUnread = evCurr->timestamp;
				}
				dbMeta.ofsLastEvent = dwOffset;
				evMeta = evCurr;
			}

			dwOffset = dwNext;
		}

		DBWrite(ccSub->dwDriverData, &dbSub, sizeof(DBContact));
		DBWrite(ccMeta->dwDriverData, &dbMeta, sizeof(DBContact));
	}
	__except (EXCEPTION_EXECUTE_HANDLER)
	{
		ret = 3;
	}

	FlushViewOfFile(m_pDbCache, 0);
	return ret;
}
예제 #8
0
BOOL CDb3Mmap::MetaMergeHistory(DBCachedContact *ccMeta, DBCachedContact *ccSub)
{
	mir_cslock lck(m_csDbAccess);
	DBContact *dbMeta = (DBContact*)DBRead(ccMeta->dwDriverData, NULL);
	DBContact *dbSub = (DBContact*)DBRead(ccSub->dwDriverData, NULL);
	if (dbMeta->signature != DBCONTACT_SIGNATURE || dbSub->signature != DBCONTACT_SIGNATURE)
		return 1;

	// special cases
	if (dbSub->ofsFirstEvent == 0) // hurrah, nothing to do
		return 0;

	LIST<DBEvent> arEvents(20000, SortEvent);
	BOOL ret = 0;
	__try {
		if (dbMeta->ofsFirstEvent == 0) { // simply chain history to a meta
			dbMeta->eventCount = dbSub->eventCount;
			dbMeta->ofsFirstEvent = dbSub->ofsFirstEvent;
			dbMeta->ofsLastEvent = dbSub->ofsLastEvent;
			dbMeta->ofsFirstUnread = dbSub->ofsFirstUnread;
			dbMeta->tsFirstUnread = dbSub->tsFirstUnread;
		}
		else {
			// there're events in both meta's & sub's event chains
			// relink sub's event chain to meta without changing events themselves
			for (DWORD ofsMeta = dbMeta->ofsFirstEvent; ofsMeta != 0;) {
				DBEvent *pev = (DBEvent*)DBRead(ofsMeta, NULL);
				if (pev->signature != DBEVENT_SIGNATURE) { // broken chain, don't touch it
					ret = 2;
					__leave;
				}

				arEvents.insert(pev);
				ofsMeta = pev->ofsNext;
			}

			for (DWORD ofsSub = dbSub->ofsFirstEvent; ofsSub != 0;) {
				DBEvent *pev = (DBEvent*)DBRead(ofsSub, NULL);
				if (pev->signature != DBEVENT_SIGNATURE) { // broken chain, don't touch it
					ret = 2;
					__leave;
				}

				arEvents.insert(pev);
				ofsSub = pev->ofsNext;
			}

			// all events are in memory, valid & sorted in the right order.
			// ready? steady? go!
			dbMeta->eventCount = arEvents.getCount();

			DBEvent *pFirst = arEvents[0];
			dbMeta->ofsFirstEvent = DWORD(PBYTE(pFirst) - m_pDbCache);
			pFirst->ofsPrev = 0;
			dbMeta->ofsFirstUnread = pFirst->markedRead() ? 0 : dbMeta->ofsFirstEvent;

			DBEvent *pLast = arEvents[arEvents.getCount() - 1];
			dbMeta->ofsLastEvent = DWORD(PBYTE(pLast) - m_pDbCache);
			pLast->ofsNext = 0;

			for (int i = 1; i < arEvents.getCount(); i++) {
				DBEvent *pPrev = arEvents[i - 1], *pNext = arEvents[i];
				pPrev->ofsNext = DWORD(PBYTE(pNext) - m_pDbCache);
				pNext->ofsPrev = DWORD(PBYTE(pPrev) - m_pDbCache);

				if (dbMeta->ofsFirstUnread == 0 && !pNext->markedRead())
					dbMeta->ofsFirstUnread = pPrev->ofsNext;
			}
		}

		// remove any traces of history from sub
		dbSub->ofsFirstEvent = dbSub->ofsLastEvent = dbSub->ofsFirstUnread = dbSub->tsFirstUnread = 0;
	}
	__except (EXCEPTION_EXECUTE_HANDLER)
	{
		ret = 3;
	}

	FlushViewOfFile(m_pDbCache, 0);
	return ret;
}