From 7578f068b6dd10641ced7d08d5eebb4654c4911c Mon Sep 17 00:00:00 2001 From: Vadim Dashevskiy Date: Fri, 14 Feb 2014 15:34:14 +0000 Subject: Dbx_tree moved to deprecated git-svn-id: http://svn.miranda-ng.org/main/trunk@8122 1316c22d-e87f-b044-9b9b-93d7a3e3ba9c --- plugins/!Deprecated/Dbx_tree/src/Events.cpp | 983 ++++++++++++++++++++++++++++ 1 file changed, 983 insertions(+) create mode 100644 plugins/!Deprecated/Dbx_tree/src/Events.cpp (limited to 'plugins/!Deprecated/Dbx_tree/src/Events.cpp') diff --git a/plugins/!Deprecated/Dbx_tree/src/Events.cpp b/plugins/!Deprecated/Dbx_tree/src/Events.cpp new file mode 100644 index 0000000000..11870f1d1f --- /dev/null +++ b/plugins/!Deprecated/Dbx_tree/src/Events.cpp @@ -0,0 +1,983 @@ +/* + +dbx_tree: tree database driver for Miranda IM + +Copyright 2007-2010 Michael "Protogenes" Kunz, + +This program is free software; you can redistribute it and/or +modify it under the terms of the GNU General Public License +as published by the Free Software Foundation; either version 2 +of the License, or (at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program; if not, write to the Free Software +Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + +*/ + +#include "Interface.h" +#include "Events.h" + +CEventsTypeManager::CEventsTypeManager(CEntities & Entities, CSettings & Settings) +: m_Entities(Entities), + m_Settings(Settings), + m_Map() +{ + m_Settings._EnsureModuleExists("$EventTypes"); +} +CEventsTypeManager::~CEventsTypeManager() +{ + TTypeMap::iterator it = m_Map.begin(); + + while (it != m_Map.end()) + { + delete [] it->second->ModuleName; + delete it->second; + ++it; + } +} + +uint32_t CEventsTypeManager::MakeGlobalID(char* Module, uint32_t EventType) +{ + uint32_t l = static_cast(strlen(Module)); + void * buf = malloc(l + sizeof(uint32_t)); + memcpy(buf, Module, l); + memcpy(((char*)buf) + l, &EventType, sizeof(uint32_t)); + + uint32_t h = Hash(buf, l + sizeof(uint32_t)); + free(buf); + + char * m; + uint32_t t; + while (GetType(h, m, t) && ((t != EventType) || (strcmp(m, Module) != 0))) + { + ++h; + } + + return h; +} +bool CEventsTypeManager::GetType(uint32_t GlobalID, char * & Module, uint32_t & EventType) +{ + TTypeMap::iterator it = m_Map.find(GlobalID); + + if (it == m_Map.end()) + { + char n[256]; + + TDBTSettingDescriptor d = {0,0,0,0,0,0,0,0}; + d.cbSize = sizeof(d); + d.Entity = m_Entities.getRootEntity(); + d.pszSettingName = n; + + TDBTSetting sid = {0,0,0,0}; + TDBTSetting sname = {0,0,0,0}; + + sid.cbSize = sizeof(sid); + sid.Descriptor = &d; + sid.Type = DBT_ST_INT; + + sname.cbSize = sizeof(sname); + sname.Descriptor = &d; + sname.Type = DBT_ST_ANSI; + + mir_snprintf(n, SIZEOF(n), "$EventTypes/%08x/ModuleID", GlobalID); + TDBTSettingHandle h = m_Settings.ReadSetting(sid); + + if ((h != DBT_INVALIDPARAM) && (h != 0)) + { + mir_snprintf(n, SIZEOF(n), "$EventTypes/%08x/ModuleName", GlobalID); + d.Flags = 0; + h = m_Settings.ReadSetting(sname); + + if ((h != DBT_INVALIDPARAM) && (h != 0)) + { + PEventType t = new TEventType; + + t->EventType = sid.Value.Int; + + t->ModuleName = new char[sname.Value.Length]; + strcpy_s(t->ModuleName, sname.Value.Length, sname.Value.pAnsi); + + m_Map.insert(std::make_pair(GlobalID, t)); + + mir_free(sname.Value.pAnsi); + + Module = t->ModuleName; + EventType = t->EventType; + + return true; + } + } + } else { + Module = it->second->ModuleName; + EventType = it->second->EventType; + + return true; + } + + return false; +} + +uint32_t CEventsTypeManager::EnsureIDExists(char* Module, uint32_t EventType) +{ + uint32_t res = MakeGlobalID(Module, EventType); + char * m; + uint32_t t; + if (!GetType(res, m, t)) + { + char n[256]; + + TDBTSettingDescriptor d = {0,0,0,0,0,0,0,0}; + d.cbSize = sizeof(d); + d.pszSettingName = n; + d.Entity = m_Entities.getRootEntity(); + + TDBTSetting s = {0,0,0,0}; + s.cbSize = sizeof(s); + s.Descriptor = &d; + + mir_snprintf(n, SIZEOF(n), "$EventTypes/%08x/ModuleID", res); + s.Type = DBT_ST_INT; + s.Value.Int = EventType; + m_Settings.WriteSetting(s); + + mir_snprintf(n, SIZEOF(n), "$EventTypes/%08x/ModuleName", res); + d.Flags = 0; + s.Type = DBT_ST_ANSI; + s.Value.Length = static_cast(strlen(Module) + 1); + s.Value.pAnsi = Module; + m_Settings.WriteSetting(s); + + m_Settings._EnsureModuleExists(Module); + } + + return res; +} + + +CEvents::CEvents( + CBlockManager & BlockManager, + CEncryptionManager & EncryptionManager, + CEntities & Entities, + CSettings & Settings +) +: m_BlockManager(BlockManager), + m_EncryptionManager(EncryptionManager), + m_Entities(Entities), + m_Types(Entities, Settings), + m_EntityEventsMap() +{ + m_Entities._sigDeleteEvents().connect(this, &CEvents::onDeleteEvents); + m_Entities._sigTransferEvents().connect(this, &CEvents::onTransferEvents); +} + +CEvents::~CEvents() +{ + TEntityEventsMap::iterator i = m_EntityEventsMap.begin(); + while (i != m_EntityEventsMap.end()) + { + delete i->second->RealTree; + delete i->second->VirtualTree; + delete i->second; + ++i; + } +} + +void CEvents::onRootChanged(void* EventsTree, CEventsTree::TNodeRef NewRoot) +{ + m_Entities._setEventsRoot(reinterpret_cast(EventsTree)->Entity(), NewRoot); +} + +void CEvents::onDeleteEventCallback(void * Tree, const TEventKey & Key, uint32_t Param) +{ + m_BlockManager.DeleteBlock(Key.Event); +} + +void CEvents::onDeleteVirtualEventCallback(void * Tree, const TEventKey & Key, uint32_t Param) +{ + m_BlockManager.DeleteBlock(Key.Event); +} +void CEvents::onDeleteEvents(CEntities * Entities, TDBTEntityHandle hEntity) +{ + PEntityEventsRecord record = getEntityRecord(hEntity); + + if (record == NULL) + return; + + m_Entities._setEventsRoot(hEntity, 0); + + if (record->VirtualCount) + { + CVirtualEventsTree::TDeleteCallback callback; + callback.connect(this, &CEvents::onDeleteVirtualEventCallback); + + record->VirtualTree->DeleteTree(&callback, hEntity); + } + delete record->VirtualTree; + + CEventsTree::TDeleteCallback callback; + callback.connect(this, &CEvents::onDeleteEventCallback); + record->RealTree->DeleteTree(&callback, hEntity); + delete record->RealTree; + m_EntityEventsMap.erase(hEntity); +} +void CEvents::onTransferEvents(CEntities * Entities, TDBTEntityHandle Source, TDBTEntityHandle Dest) +{ + PEntityEventsRecord record = getEntityRecord(Source); + + if (record == NULL) + return; + + if (record->VirtualCount) + { + TEventKey key = {0,0}; + + CVirtualEventsTree::iterator i = record->VirtualTree->LowerBound(key); + + while (i) + { + uint32_t sig = cEventSignature; + uint32_t size = 0; + TEvent * tmp = m_BlockManager.ReadBlock(i->Event, size, sig); + if (tmp) + { + tmp->Entity = Dest; + m_BlockManager.UpdateBlock(i->Event); + } + ++i; + } + } + + { + TEventKey key = {0,0}; + + CEventsTree::iterator i = record->RealTree->LowerBound(key); + while (i) + { + uint32_t sig = cEventSignature; + uint32_t size = 0; + TEvent * tmp = m_BlockManager.ReadBlock(i->Event, size, sig); + if (tmp) + { + tmp->Entity = Dest; + m_BlockManager.UpdateBlock(i->Event); + } + ++i; + } + + m_Entities._setEventsRoot(Source, 0); + m_Entities._setEventsRoot(Dest, record->RealTree->getRoot()); + m_Entities._adjustEventCount(Dest, m_Entities._getEventCount(Source)); + m_Entities._getFirstUnreadEvent(Source, key.Event, key.TimeStamp); + m_Entities._setFirstUnreadEvent(Dest, key.Event, key.TimeStamp); + } + + record->VirtualTree->Entity(Dest); + record->RealTree->Entity(Dest); + m_EntityEventsMap.erase(Source); + m_EntityEventsMap.insert(std::make_pair(Dest, record)); +} + +CEvents::PEntityEventsRecord CEvents::getEntityRecord(TDBTEntityHandle hEntity) +{ + TEntityEventsMap::iterator i = m_EntityEventsMap.find(hEntity); + if (i != m_EntityEventsMap.end()) + return i->second; + + uint32_t root = m_Entities._getEventsRoot(hEntity); + if (root == DBT_INVALIDPARAM) + return NULL; + + PEntityEventsRecord res = new TEntityEventsRecord; + res->RealTree = new CEventsTree(m_BlockManager, root, hEntity); + res->RealTree->sigRootChanged().connect(this, &CEvents::onRootChanged); + res->VirtualTree = new CVirtualEventsTree(hEntity); + res->VirtualCount = 0; + res->FirstVirtualUnread.TimeStamp = 0; + res->FirstVirtualUnread.Event = 0; + m_EntityEventsMap.insert(std::make_pair(hEntity, res)); + + return res; +} + +inline uint32_t CEvents::adjustVirtualEventCount(PEntityEventsRecord Record, int32_t Adjust) +{ + if (((Adjust < 0) && ((uint32_t)(-Adjust) <= Record->VirtualCount)) || + ((Adjust > 0) && ((0xffffffff - Record->VirtualCount) > (uint32_t)Adjust))) + { + Record->VirtualCount += Adjust; + } + + return Record->VirtualCount; +} + +inline bool CEvents::MarkEventsTree(TEventBase::iterator Iterator, TDBTEventHandle FirstUnread) +{ + uint32_t sig, size; + bool b = true; + bool res = false; + while (Iterator && b) + { + sig = cEventSignature; + size = 0; + TEvent * event = m_BlockManager.ReadBlock(Iterator->Event, size, sig); + if (event) + { + if (Iterator->Event == FirstUnread) + res = true; + + if ((event->Flags & DBT_EF_READ) == 0) + { + event->Flags |= DBT_EF_READ; + m_BlockManager.UpdateBlock(Iterator->Event); + --Iterator; + } else { + b = false; + } + } else { + --Iterator; + } + } + return res; +} +inline void CEvents::FindNextUnreadEvent(TEventBase::iterator & Iterator) +{ + uint32_t sig, size; + while (Iterator) + { + sig = cEventSignature; + size = 0; + TEvent * event = m_BlockManager.ReadBlock(Iterator->Event, size, sig); + if (event) + { + if (event->Flags & DBT_EF_READ) + ++Iterator; + else + return; + } else { + ++Iterator; + } + } +} + +unsigned int CEvents::GetBlobSize(TDBTEventHandle hEvent) +{ + uint32_t sig = cEventSignature; + uint32_t size = 0; + + CBlockManager::ReadTransaction trans(m_BlockManager); + TEvent * event = m_BlockManager.ReadBlock(hEvent, size, sig); + if (!event) + return DBT_INVALIDPARAM; + + return event->DataLength; +} + +unsigned int CEvents::Get(TDBTEventHandle hEvent, TDBTEvent & Event) +{ + uint32_t sig = cEventSignature; + uint32_t size = 0; + + CBlockManager::ReadTransaction trans(m_BlockManager); + + TEvent * event = m_BlockManager.ReadBlock(hEvent, size, sig); + if (!event) + return DBT_INVALIDPARAM; + + uint8_t * blob = reinterpret_cast(event + 1); + + if (!m_Types.GetType(event->Type, Event.ModuleName, Event.EventType)) + { + Event.EventType = event->Type; + Event.ModuleName = "???"; + } + + Event.Flags = event->Flags; + if (m_BlockManager.IsForcedVirtual(hEvent)) + Event.Flags |= DBT_EF_VIRTUAL; + + Event.Timestamp = event->TimeStamp; + + if (Event.cbBlob < event->DataLength) + Event.pBlob = (uint8_t*) mir_realloc(Event.pBlob, event->DataLength); + + memcpy(Event.pBlob, blob, event->DataLength); + Event.cbBlob = event->DataLength; + + return 0; +} + +unsigned int CEvents::GetCount(TDBTEntityHandle hEntity) +{ + CBlockManager::ReadTransaction trans(m_BlockManager); + + uint32_t res = m_Entities._getEventCount(hEntity); + PEntityEventsRecord record = getEntityRecord(hEntity); + + if ((res == DBT_INVALIDPARAM) || !record) + return DBT_INVALIDPARAM; + + res = res + record->VirtualCount; // access to Virtual Count need sync, too + + return res; +} + +unsigned int CEvents::Delete(TDBTEventHandle hEvent) +{ + uint32_t sig = cEventSignature; + uint32_t size = 0; + TEventKey key = {0, hEvent}; + + CBlockManager::WriteTransaction trans(m_BlockManager); + + TEvent * event = m_BlockManager.ReadBlock(hEvent, size, sig); + if (!event) + return DBT_INVALIDPARAM; + + key.TimeStamp = event->TimeStamp; + + PEntityEventsRecord record = getEntityRecord(event->Entity); + if (!record) + return DBT_INVALIDPARAM; + + if (m_BlockManager.IsForcedVirtual(hEvent)) + { + if (record->VirtualTree->Delete(key)) + { + adjustVirtualEventCount(record, -1); + + if (record->FirstVirtualUnread.Event == hEvent) + { + CVirtualEventsTree::iterator vi = record->VirtualTree->LowerBound(key); + FindNextUnreadEvent(vi); + if (vi) + { + record->FirstVirtualUnread = *vi; + } else { + record->FirstVirtualUnread.TimeStamp = 0; + record->FirstVirtualUnread.Event = 0; + } + } + } + } else { // real event + if (record->RealTree->Delete(key)) + { + m_Entities._adjustEventCount(event->Entity, -1); + TEventKey unreadkey; + m_Entities._getFirstUnreadEvent(event->Entity, unreadkey.Event, unreadkey.TimeStamp); + if (unreadkey.Event == hEvent) + { + CEventsTree::iterator it = record->VirtualTree->LowerBound(key); + FindNextUnreadEvent(it); + if (it) + { + m_Entities._setFirstUnreadEvent(event->Entity, it->Event, it->TimeStamp); + } else { + m_Entities._setFirstUnreadEvent(event->Entity, 0, 0); + } + } + } + } + m_BlockManager.DeleteBlock(hEvent); + + return 0; +} + +TDBTEventHandle CEvents::Add(TDBTEntityHandle hEntity, TDBTEvent & Event) +{ + TDBTEventHandle res = 0; + TEvent * event; + + CBlockManager::WriteTransaction trans(m_BlockManager); + + uint32_t eflags = m_Entities.getFlags(hEntity); + PEntityEventsRecord record = getEntityRecord(hEntity); + + if ((eflags == DBT_INVALIDPARAM) || + ((eflags & (DBT_NF_IsGroup | DBT_NF_IsRoot)) == DBT_NF_IsGroup) || // forbid events in groups. but allow root to have system history + !record) + { + return DBT_INVALIDPARAM; + } + + if (eflags & DBT_NF_IsVirtual) + hEntity = m_Entities.VirtualGetParent(hEntity); + + uint8_t *blobdata = Event.pBlob; + bool bloballocated = false; + + if (Event.Flags & DBT_EF_VIRTUAL) + { + event = m_BlockManager.CreateBlockVirtual(res, cEventSignature, sizeof(TEvent) + Event.cbBlob); + } else { + event = m_BlockManager.CreateBlock(res, cEventSignature, sizeof(TEvent) + Event.cbBlob); + } + + if (!event) + return DBT_INVALIDPARAM; + + TEventKey key = {0,0}; + + event->TimeStamp = Event.Timestamp; + event->Flags = Event.Flags & ~DBT_EF_VIRTUAL; + event->Type = m_Types.EnsureIDExists(Event.ModuleName, Event.EventType); + event->DataLength = Event.cbBlob; + event->Entity = hEntity; + + key.TimeStamp = event->TimeStamp; + key.Event = res; + memcpy(event + 1, Event.pBlob, Event.cbBlob); + + m_BlockManager.UpdateBlock(res); + + if (Event.Flags & DBT_EF_VIRTUAL) + { + record->VirtualTree->Insert(key); + adjustVirtualEventCount(record, +1); + if (!(Event.Flags & DBT_EF_READ) && ((record->FirstVirtualUnread.Event == 0) || (key < record->FirstVirtualUnread))) + { + record->FirstVirtualUnread = key; + } + } else { + record->RealTree->Insert(key); + m_Entities._adjustEventCount(hEntity, +1); + + if (!(Event.Flags & DBT_EF_READ)) + { + TEventKey unreadkey; + if (m_Entities._getFirstUnreadEvent(hEntity, unreadkey.Event, unreadkey.TimeStamp) && + ((unreadkey.Event == 0) || (key < unreadkey))) + { + m_Entities._setFirstUnreadEvent(hEntity, key.Event, key.TimeStamp); + } + } + } + + return res; +} +unsigned int CEvents::MarkRead(TDBTEventHandle hEvent) +{ + uint32_t sig = cEventSignature; + uint32_t size = 0; + TEventKey key = {0, hEvent}; + + CBlockManager::WriteTransaction trans(m_BlockManager); + + TEvent * event = m_BlockManager.ReadBlock(hEvent, size, sig); + + if (!event) + return DBT_INVALIDPARAM; + + key.TimeStamp = event->TimeStamp; + + if (event->Flags & DBT_EF_READ) + return event->Flags; + + PEntityEventsRecord record = getEntityRecord(event->Entity); + if (!record) + return DBT_INVALIDPARAM; + + CEventsTree::iterator it = record->RealTree->UpperBound(key); + CVirtualEventsTree::iterator vi = record->VirtualTree->UpperBound(key); + + m_Entities._getFirstUnreadEvent(event->Entity, key.Event, key.TimeStamp); + if (MarkEventsTree(it, key.Event)) + { + FindNextUnreadEvent(++it); + if (it) + { + m_Entities._setFirstUnreadEvent(event->Entity, it->Event, it->TimeStamp); + } else { + m_Entities._setFirstUnreadEvent(event->Entity, 0, 0); + } + } + if (MarkEventsTree(vi, record->FirstVirtualUnread.Event)) + { + FindNextUnreadEvent(++vi); + if (vi) + { + record->FirstVirtualUnread = *it; + } else { + record->FirstVirtualUnread.TimeStamp = 0; + record->FirstVirtualUnread.Event = 0; + } + } + + return event->Flags | DBT_EF_READ; +} +unsigned int CEvents::WriteToDisk(TDBTEventHandle hEvent) +{ + uint32_t sig = cEventSignature; + uint32_t size = 0; + TEventKey key; + key.Event = hEvent; + + CBlockManager::WriteTransaction trans(m_BlockManager); + + if (!m_BlockManager.IsForcedVirtual(hEvent)) + return DBT_INVALIDPARAM; + + TEvent * event = m_BlockManager.ReadBlock(hEvent, size, sig); + if (!event || (size < sizeof(TEvent))) + return DBT_INVALIDPARAM; + + PEntityEventsRecord record = getEntityRecord(event->Entity); + if (!record) + return DBT_INVALIDPARAM; + + key.TimeStamp = event->TimeStamp; + key.Event = hEvent; + + if (record->VirtualTree->Delete(key)) + adjustVirtualEventCount(record, -1); + + if (record->RealTree->Insert(key)) + m_Entities._adjustEventCount(event->Entity, +1); + m_BlockManager.WriteBlockToDisk(hEvent); + + return 0; +} + +TDBTEntityHandle CEvents::getEntity(TDBTEventHandle hEvent) +{ + uint32_t sig = cEventSignature; + uint32_t size = 0; + + CBlockManager::ReadTransaction trans(m_BlockManager); + TEvent * event = m_BlockManager.ReadBlock(hEvent, size, sig); + if (!event) + return DBT_INVALIDPARAM; + + return event->Entity; +} + +TDBTEventIterationHandle CEvents::IterationInit(TDBTEventIterFilter & Filter) +{ + CBlockManager::ReadTransaction trans(m_BlockManager); + + PEntityEventsRecord record = getEntityRecord(Filter.hEntity); + + if (!record) + return DBT_INVALIDPARAM; + + std::queue q; + q.push(record->RealTree); + q.push(record->VirtualTree); + + TDBTEntityIterFilter f = {0,0,0,0}; + f.cbSize = sizeof(f); + f.Options = Filter.Options; + + TDBTEntityIterationHandle citer = m_Entities.IterationInit(f, Filter.hEntity); + if (citer != DBT_INVALIDPARAM) + { + m_Entities.IterationNext(citer); + TDBTEntityHandle c = m_Entities.IterationNext(citer); + while (c != 0) + { + record = getEntityRecord(c); + if (record) + { + q.push(record->RealTree); + q.push(record->VirtualTree); + } + + c = m_Entities.IterationNext(citer); + } + + m_Entities.IterationClose(citer); + } + + for (unsigned j = 0; j < Filter.ExtraCount; ++j) + { + record = getEntityRecord(Filter.ExtraEntities[j]); + if (record) + { + q.push(record->RealTree); + q.push(record->VirtualTree); + } + } + + PEventIteration iter = new TEventIteration; + iter->Filter = Filter; + iter->LastEvent = 0; + iter->Heap = NULL; + + TEventKey key; + key.TimeStamp = Filter.tSince; + key.Event = 0; + + while (!q.empty()) + { + TEventBase * b = q.front(); + q.pop(); + + TEventBase::iterator it = b->LowerBound(key); + if (it) + { + TEventBase::iterator * it2 = new TEventBase::iterator(it); + it2->setManaged(); + if (iter->Heap) + { + iter->Heap->Insert(*it2); + } else { + iter->Heap = new TEventsHeap(*it2, TEventsHeap::ITForward, true); + } + } + } + + if (iter->Heap == NULL) + { + delete iter; + iter = (PEventIteration)DBT_INVALIDPARAM; + } + + return reinterpret_cast(iter); +} + +TDBTEventHandle CEvents::IterationNext(TDBTEventIterationHandle Iteration) +{ + PEventIteration iter = reinterpret_cast(Iteration); + + CBlockManager::ReadTransaction trans(m_BlockManager); + + TDBTEventHandle res = 0; + TEventBase::iterator it = iter->Heap->Top(); + + while ((it) && (it.wasDeleted() || ((it->TimeStamp <= iter->Filter.tTill) && (it->Event == iter->LastEvent)))) + { + iter->Heap->Pop(); + it = iter->Heap->Top(); + } + + if ((it) && !it.wasDeleted() && (it->TimeStamp <= iter->Filter.tTill)) + { + res = it->Event; + iter->Heap->Pop(); + } + + if (res) + { + iter->LastEvent = res; + if (iter->Filter.Event) + { + iter->Filter.Event->EventType = 0; + Get(res, *iter->Filter.Event); + } + } + + return res; +} + +unsigned int CEvents::IterationClose(TDBTEventIterationHandle Iteration) +{ + PEventIteration iter = reinterpret_cast(Iteration); + + CBlockManager::ReadTransaction trans(m_BlockManager); + delete iter->Heap; + delete iter; + return 0; +} + + +TDBTEventHandle CEvents::compFirstEvent(TDBTEntityHandle hEntity) +{ + CBlockManager::ReadTransaction trans(m_BlockManager); + + TDBTEventHandle res = 0; + + PEntityEventsRecord record = getEntityRecord(hEntity); + if (!record) + return 0; + + TEventKey key = {0,0}; + CEventsTree::iterator i = record->RealTree->LowerBound(key); + CVirtualEventsTree::iterator vi = record->VirtualTree->LowerBound(key); + + if (i && vi) + { + if (*i < *vi) + { + res = i->Event; + } else { + res = vi->Event; + } + } else if (i) + { + res = i->Event; + } else if (vi) + { + res = vi->Event; + } + + return res; +} +TDBTEventHandle CEvents::compFirstUnreadEvent(TDBTEntityHandle hEntity) +{ + CBlockManager::ReadTransaction trans(m_BlockManager); + + TDBTEventHandle res = 0; + + PEntityEventsRecord record = getEntityRecord(hEntity); + if (!record) + return 0; + + TEventKey key; + m_Entities._getFirstUnreadEvent(hEntity, key.Event, key.TimeStamp); + if (key.Event) + { + if (record->FirstVirtualUnread.Event && (record->FirstVirtualUnread < key)) + { + res = record->FirstVirtualUnread.Event; + } else { + res = key.Event; + } + } else if (record->FirstVirtualUnread.Event) + { + res = record->FirstVirtualUnread.Event; + } + + return res; +} +TDBTEventHandle CEvents::compLastEvent(TDBTEntityHandle hEntity) +{ + CBlockManager::ReadTransaction trans(m_BlockManager); + TDBTEventHandle res = 0; + + PEntityEventsRecord record = getEntityRecord(hEntity); + if (!record) + return 0; + + TEventKey key = {0xffffffff, 0xffffffff}; + + CEventsTree::iterator i = record->RealTree->UpperBound(key); + CVirtualEventsTree::iterator vi = record->VirtualTree->UpperBound(key); + + if (i && vi) + { + if (*i > *vi) + { + res = i->Event; + } else { + res = vi->Event; + } + } else if (i) + { + res = i->Event; + } else if (vi) + { + res = vi->Event; + } + + return res; +} +TDBTEventHandle CEvents::compNextEvent(TDBTEventHandle hEvent) +{ + uint32_t sig = cEventSignature; + uint32_t size = 0; + + CBlockManager::ReadTransaction trans(m_BlockManager); + + TEvent * event = m_BlockManager.ReadBlock(hEvent, size, sig); + + if (!event) + return 0; + + TEventKey key = {event->TimeStamp, hEvent}; + + PEntityEventsRecord record = getEntityRecord(event->Entity); + + if (!record) + return 0; + + if (key.Event == 0xffffffff) + { + if (key.TimeStamp == 0xffffffff) + { + return 0; + } else { + ++key.TimeStamp; + } + } else { + ++key.Event; + } + + CEventsTree::iterator i = record->RealTree->LowerBound(key); + CVirtualEventsTree::iterator vi = record->VirtualTree->LowerBound(key); + + TDBTEventHandle res = 0; + if (i && vi) + { + if (*i < *vi) + { + res = i->Event; + } else { + res = vi->Event; + } + } else if (i) + { + res = i->Event; + } else if (vi) + { + res = vi->Event; + } + + return res; +} +TDBTEventHandle CEvents::compPrevEvent(TDBTEventHandle hEvent) +{ + uint32_t sig = cEventSignature; + uint32_t size = 0; + + CBlockManager::ReadTransaction trans(m_BlockManager); + + TEvent * event = m_BlockManager.ReadBlock(hEvent, size, sig); + + if (!event) + return 0; + + TEventKey key = {event->TimeStamp, hEvent}; + + PEntityEventsRecord record = getEntityRecord(event->Entity); + if (!record) + return 0; + + if (key.Event == 0) + { + if (key.TimeStamp == 0) + { + return 0; + } else { + --key.TimeStamp; + } + } else { + --key.Event; + } + + CEventsTree::iterator i = record->RealTree->UpperBound(key); + CVirtualEventsTree::iterator vi = record->VirtualTree->UpperBound(key); + + TDBTEventHandle res = 0; + if (i && vi) + { + if (*i > *vi) + { + res = i->Event; + } else { + res = vi->Event; + } + } else if (i) + { + res = i->Event; + } else if (vi) + { + res = vi->Event; + } + + return res; +} -- cgit v1.2.3