From f04d64869f3b1de54fb343f28f955584780001b8 Mon Sep 17 00:00:00 2001 From: mataes2007 Date: Sat, 26 Nov 2011 15:41:10 +0000 Subject: Project folders rename part 3 git-svn-id: http://miranda-plugins.googlecode.com/svn/trunk@215 e753b5eb-9565-29b2-b5c5-2cc6f99dfbcb --- Dbx_mmap_SA/Dbtool/eventchain.cpp | 363 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 363 insertions(+) create mode 100644 Dbx_mmap_SA/Dbtool/eventchain.cpp (limited to 'Dbx_mmap_SA/Dbtool/eventchain.cpp') diff --git a/Dbx_mmap_SA/Dbtool/eventchain.cpp b/Dbx_mmap_SA/Dbtool/eventchain.cpp new file mode 100644 index 0000000..c48ab1b --- /dev/null +++ b/Dbx_mmap_SA/Dbtool/eventchain.cpp @@ -0,0 +1,363 @@ +/* +Miranda Database Tool +Miranda IM: the free IM client for Microsoft* Windows* + +Copyright 2000-2011 Miranda ICQ/IM project, +all portions of this codebase are copyrighted to the people +listed in contributors.txt. + +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 "dbtool.h" + +static BOOL backLookup; +static DWORD ofsThisEvent,ofsPrevEvent; +static DWORD ofsDestPrevEvent; +static DWORD eventCount; +static DWORD lastTimestamp; +static DWORD ofsFirstUnread,timestampFirstUnread; +static DWORD memsize = 0; +static DBEvent* memblock = NULL; +static DBEvent* dbePrevEvent = NULL; + +static void ConvertOldEvent( DBEvent*& dbei ) +{ + int msglen = (int)strlen(( char* )dbei->blob) + 1, msglenW = 0; + if ( msglen != (int) dbei->cbBlob ) { + int i, count = (( dbei->cbBlob - msglen ) / sizeof( WCHAR )); + WCHAR* p = ( WCHAR* )&dbei->blob[ msglen ]; + for ( i=0; i < count; i++ ) { + if ( p[i] == 0 ) { + msglenW = i; + break; + } } } + else { + if( !is_utf8_string(( char* )dbei->blob) ) + dbei->flags &= ~DBEF_UTF; + } + + if ( msglenW > 0 && msglenW <= msglen ) { + char* utf8str = Utf8EncodeUcs2(( WCHAR* )&dbei->blob[ msglen ] ); + dbei->cbBlob = (DWORD)strlen( utf8str )+1; + dbei->flags |= DBEF_UTF; + if (offsetof(DBEvent,blob)+dbei->cbBlob > memsize) { + memsize = offsetof(DBEvent,blob)+dbei->cbBlob; + memblock = (DBEvent*)realloc(memblock, memsize); + dbei = memblock; + } + memcpy( &dbei->blob, utf8str, dbei->cbBlob ); + free(utf8str); +} } + +static void WriteOfsNextToPrevious(DWORD ofsPrev,DBContact *dbc,DWORD ofsNext) +{ + if(ofsPrev) + WriteSegment(ofsPrev+offsetof(DBEvent,ofsNext),&ofsNext,sizeof(DWORD)); + else + dbc->ofsFirstEvent=ofsNext; +} + +static void FinishUp(DWORD ofsLast,DBContact *dbc) +{ + WriteOfsNextToPrevious(ofsLast,dbc,0); + if(eventCount!=dbc->eventCount) + AddToStatus(STATUS_WARNING,TranslateT("Event count marked wrongly: correcting")); + dbc->eventCount=eventCount; + dbc->ofsLastEvent=ofsLast; + if(opts.bMarkRead) { + dbc->ofsFirstUnreadEvent=0; + dbc->timestampFirstUnread=0; + } + else { + dbc->ofsFirstUnreadEvent=ofsFirstUnread; + dbc->timestampFirstUnread=timestampFirstUnread; + } + if (memsize && memblock) { + free(memblock); + memsize = 0; + memblock = NULL; + } +} + +static DWORD WriteEvent(DBEvent *dbe) +{ + DWORD ofs = WriteSegment( WSOFS_END, dbe, offsetof(DBEvent,blob)+dbe->cbBlob ); + if ( ofs == WS_ERROR ) { + free( memblock ); + memblock = NULL; + memsize = 0; + return 0; + } + return ofs; +} + +int WorkEventChain(DWORD ofsContact,DBContact *dbc,int firstTime) +{ + DBEvent *dbeNew,dbeOld; + DBEvent *dbePrev = NULL; + DWORD ofsDestThis; + int isUnread=0; + + if(firstTime) { + dbePrevEvent = NULL; + ofsPrevEvent=0; + ofsDestPrevEvent=0; + ofsThisEvent=dbc->ofsFirstEvent; + eventCount=0; + backLookup=0; + lastTimestamp=0; + ofsFirstUnread=timestampFirstUnread=0; + if(opts.bEraseHistory) { + dbc->eventCount=0; + dbc->ofsFirstEvent=0; + dbc->ofsLastEvent=0; + dbc->ofsFirstUnreadEvent=0; + dbc->timestampFirstUnread=0; + return ERROR_NO_MORE_ITEMS; + } } + + if(ofsThisEvent==0) { + FinishUp(ofsDestPrevEvent,dbc); + return ERROR_NO_MORE_ITEMS; + } + if(!SignatureValid(ofsThisEvent,DBEVENT_SIGNATURE)) + { + DWORD ofsNew = 0; + DWORD ofsTmp = dbc->ofsLastEvent; + + if (!backLookup && ofsTmp) { + backLookup = 1; + while(SignatureValid(ofsTmp,DBEVENT_SIGNATURE)) + { + if(PeekSegment(ofsTmp,&dbeOld,sizeof(dbeOld))!=ERROR_SUCCESS) + break; + ofsNew = ofsTmp; + ofsTmp = dbeOld.ofsPrev; + } + } + if (ofsNew) { + AddToStatus(STATUS_WARNING,TranslateT("Event chain corrupted, trying to recover...")); + ofsThisEvent = ofsNew; + } else { + AddToStatus(STATUS_ERROR,TranslateT("Event chain corrupted, further entries ignored")); + FinishUp(ofsDestPrevEvent,dbc); + return ERROR_NO_MORE_ITEMS; + } + } + + if(PeekSegment(ofsThisEvent,&dbeOld,sizeof(dbeOld))!=ERROR_SUCCESS) { + FinishUp(ofsDestPrevEvent,dbc); + return ERROR_NO_MORE_ITEMS; + } + + if(firstTime) { + if(!(dbeOld.flags&DBEF_FIRST)) { + AddToStatus(STATUS_WARNING,TranslateT("First event not marked as such: correcting")); + dbeOld.flags|=DBEF_FIRST; + } + dbeOld.ofsPrev=ofsContact; + lastTimestamp=dbeOld.timestamp; + } + else if(dbeOld.flags&DBEF_FIRST) { + AddToStatus(STATUS_WARNING,TranslateT("Event marked as first which is not: correcting")); + dbeOld.flags&=~DBEF_FIRST; + } + + if(dbeOld.flags&~(DBEF_FIRST|DBEF_READ|DBEF_SENT|DBEF_RTL|DBEF_UTF)) { + AddToStatus(STATUS_WARNING,TranslateT("Extra flags found in event: removing")); + dbeOld.flags&=(DBEF_FIRST|DBEF_READ|DBEF_SENT|DBEF_RTL|DBEF_UTF); + } + + if(!(dbeOld.flags&(DBEF_READ|DBEF_SENT))) { + if(opts.bMarkRead) dbeOld.flags|=DBEF_READ; + else if(ofsFirstUnread==0) { + if(dbc->ofsFirstUnreadEvent!=ofsThisEvent || dbc->timestampFirstUnread!=dbeOld.timestamp) + AddToStatus(STATUS_WARNING,TranslateT("First unread event marked wrong: fixing")); + isUnread=1; + } } + + if(dbeOld.cbBlob>1024*1024 || dbeOld.cbBlob==0) { + AddToStatus(STATUS_ERROR,TranslateT("Infeasibly large event blob: skipping")); + ofsThisEvent=dbeOld.ofsNext; + return ERROR_SUCCESS; + } + + if ( dbePrevEvent && dbeOld.timestamp == lastTimestamp ) { + int len = offsetof(DBEvent,blob)+dbePrevEvent->cbBlob; + dbePrev = (DBEvent*)malloc(len); + memcpy(dbePrev, dbePrevEvent, len); + } + + if (offsetof(DBEvent,blob)+dbeOld.cbBlob > memsize) { + memsize = offsetof(DBEvent,blob)+dbeOld.cbBlob; + memblock = (DBEvent*)realloc(memblock, memsize); + } + dbeNew=memblock; + + if(ReadSegment(ofsThisEvent,dbeNew,offsetof(DBEvent,blob)+dbeOld.cbBlob)!=ERROR_SUCCESS) { + FinishUp(ofsDestPrevEvent,dbc); + return ERROR_NO_MORE_ITEMS; + } + + if((dbeNew->ofsModuleName=ConvertModuleNameOfs(dbeOld.ofsModuleName))==0) { + ofsThisEvent=dbeOld.ofsNext; + return ERROR_SUCCESS; + } + + if(!firstTime && dbeOld.ofsPrev!=ofsPrevEvent) + AddToStatus(STATUS_WARNING,TranslateT("Event not backlinked correctly: fixing")); + + dbeNew->flags=dbeOld.flags; + dbeNew->ofsPrev=ofsDestPrevEvent; + dbeNew->ofsNext=0; + + if ( dbeOld.eventType == EVENTTYPE_MESSAGE && opts.bConvertUtf ) + ConvertOldEvent(dbeNew); + + if ( dbePrev ) + { + if ( dbePrev->cbBlob == dbeNew->cbBlob && + dbePrev->ofsModuleName == dbeNew->ofsModuleName && + dbePrev->eventType == dbeNew->eventType && + (dbePrev->flags & DBEF_SENT) == (dbeNew->flags & DBEF_SENT) && + !memcmp( dbePrev->blob, dbeNew->blob, dbeNew->cbBlob ) + ) { + AddToStatus(STATUS_WARNING,TranslateT("Duplicate event was found: skipping")); + if (dbc->eventCount) + dbc->eventCount--; + free(dbePrev); + // ofsDestPrevEvent is still the same! + ofsPrevEvent=ofsThisEvent; + ofsThisEvent=dbeOld.ofsNext; + return ERROR_SUCCESS; + } + free(dbePrev); + } + else if ( !firstTime && dbeNew->timestamp < lastTimestamp ) + { + DWORD found = 0; + DBEvent dbeTmp; + DWORD ofsTmp; + + if (opts.bCheckOnly) + { + if (!opts.bAggressive) + { + ofsTmp = dbeOld.ofsPrev; + while(PeekSegment(ofsTmp,&dbeTmp,sizeof(dbeTmp))==ERROR_SUCCESS) + { + if (dbeTmp.ofsPrev == ofsContact) { + found = 1; + break; + } + if (dbeTmp.timestamp < dbeNew->timestamp) { + found = 2; + break; + } + ofsTmp = dbeTmp.ofsPrev; + } + } + AddToStatus(STATUS_WARNING,TranslateT("Event position in chain is not correct")); + } + else + { + ofsTmp = ofsDestPrevEvent; + while(ReadWrittenSegment(ofsTmp,&dbeTmp,sizeof(dbeTmp))==ERROR_SUCCESS) + { + if (dbeTmp.ofsPrev == ofsContact) { + found = 1; + break; + } + if (dbeTmp.timestamp < dbeNew->timestamp) { + found = 2; + break; + } + ofsTmp = dbeTmp.ofsPrev; + } + if (found) + AddToStatus(STATUS_WARNING,TranslateT("Event position in chain is not correct: fixing")); + else + AddToStatus(STATUS_WARNING,TranslateT("Event position in chain is not correct: unable to fix")); + } + + // insert before FIRST + if (found == 1 && !opts.bCheckOnly) { + dbeNew->flags|=DBEF_FIRST; + dbeNew->ofsPrev=ofsContact; + dbeNew->ofsNext=dbc->ofsFirstEvent; + + ofsDestThis = WriteEvent(dbeNew); + if ( !ofsDestThis ) + return ERROR_HANDLE_DISK_FULL; + + if ( isUnread && timestampFirstUnread >= dbeNew->timestamp ) { + ofsFirstUnread=ofsDestThis; + timestampFirstUnread=dbeNew->timestamp; + } + // fix first event + WriteOfsNextToPrevious(0,dbc,ofsDestThis); + // fix next event + WriteSegment(dbeNew->ofsNext+offsetof(DBEvent,ofsPrev),&ofsDestThis,sizeof(DWORD)); + dbeTmp.flags &=~DBEF_FIRST; + WriteSegment(dbeNew->ofsNext+offsetof(DBEvent,flags),&dbeTmp.flags,sizeof(DWORD)); + } + else if (found == 2 && !opts.bCheckOnly) { + + dbeNew->ofsPrev=ofsTmp; + dbeNew->ofsNext=dbeTmp.ofsNext; + + ofsDestThis = WriteEvent(dbeNew); + if ( !ofsDestThis ) + return ERROR_HANDLE_DISK_FULL; + + if ( isUnread && timestampFirstUnread >= dbeNew->timestamp ) { + ofsFirstUnread=ofsDestThis; + timestampFirstUnread=dbeNew->timestamp; + } + // fix previous event + WriteOfsNextToPrevious(dbeNew->ofsPrev,dbc,ofsDestThis); + // fix next event + WriteSegment(dbeNew->ofsNext+offsetof(DBEvent,ofsPrev),&ofsDestThis,sizeof(DWORD)); + } + + if (found) { + eventCount++; + // ofsDestPrevEvent is still the same! + ofsPrevEvent=ofsThisEvent; + ofsThisEvent=dbeOld.ofsNext; + return ERROR_SUCCESS; + } + } + + lastTimestamp=dbeNew->timestamp; + dbePrevEvent = dbeNew; + + ofsDestThis = WriteEvent(dbeNew); + if ( !ofsDestThis ) + return ERROR_HANDLE_DISK_FULL; + + if ( isUnread ) { + ofsFirstUnread=ofsDestThis; + timestampFirstUnread=dbeOld.timestamp; + } + + eventCount++; + WriteOfsNextToPrevious(ofsDestPrevEvent,dbc,ofsDestThis); + + ofsDestPrevEvent=ofsDestThis; + ofsPrevEvent=ofsThisEvent; + ofsThisEvent=dbeOld.ofsNext; + return ERROR_SUCCESS; +} -- cgit v1.2.3