[prev in list] [next in list] [prev in thread] [next in thread]
List: kde-commits
Subject: KDE/kdepim/akonadi/resources/mbox/libmbox
From: Bertjan Broeksema <b.broeksema () home ! nl>
Date: 2009-06-26 14:40:09
Message-ID: 1246027209.659420.16654.nullmailer () svn ! kde ! org
[Download RAW message or body]
SVN commit 987701 by bbroeksema:
- Greatly simplify the purge method.
- Add some tests for the purge methods. (I consider it reasonably save now).
M +45 -58 mbox.cpp
M +59 -0 tests/mboxtest.cpp
M +1 -0 tests/mboxtest.h
--- trunk/KDE/kdepim/akonadi/resources/mbox/libmbox/mbox.cpp #987700:987701
@@ -337,90 +337,77 @@
QRegExp regexp( sMBoxSeperatorRegExp );
if ( regexp.indexIn(line) < 0 ) {
+ qDebug() << "Found invalid seperator at:" << offset;
unlock();
return false; // The file is messed up or the index is incorrect.
}
}
+ // All entries are deleted, so just resize the file to a size of 0.
+ if ( deletedItems.size() == d->mEntries.size() ) {
+ d->mEntries.clear();
+ d->mMboxFile.resize( 0 );
+ kDebug() << "Purge comleted successfully, unlocking the file.";
+ return unlock();
+ }
+
qSort( d->mEntries.begin(), d->mEntries.end(), lessThanByOffset );
quint64 writeOffset = 0;
+ bool writeOffSetInitialized = false;
QList<MsgInfo> resultingEntryList;
+ quint64 origFileSize = d->mMboxFile.size();
+
QListIterator<MsgInfo> i( d->mEntries );
while ( i.hasNext() ) {
MsgInfo entry = i.next();
- if ( deletedItems.contains( entry.first ) ) {
- // This entry must get removed from the file.
+ if ( deletedItems.contains( entry.first ) && !writeOffSetInitialized ) {
writeOffset = entry.first;
-
+ writeOffSetInitialized = true;
+ } else if ( writeOffset < entry.first && !deletedItems.contains( entry.first ) ) {
+ // The current message doesn't have to be deleted, but must be moved.
+ // First determine the size of the entry that must be moved.
+ quint64 entrySize = 0;
if ( i.hasNext() ) {
- // One ore more entries after this one, find the first that should be
- // kept, or find eof if all following entries must be deleted.
- MsgInfo entryToWrite;
- bool nextEntryFound = false;
- while ( i.hasNext() && !nextEntryFound ) {
- entryToWrite = i.next();
- if ( !deletedItems.contains( entryToWrite.first ) )
- nextEntryFound = true;
- }
+ entrySize = i.next().first - entry.first - 1;
+ i.previous(); // Go back to make sure that we also handle the next entry.
+ } else {
+ entrySize = origFileSize - entry.first - 1;
+ }
- if ( nextEntryFound ) {
- if ( i.hasNext() ) { // Read the next entry to determine the size.
- MsgInfo entryAfterEntryToWrite = i.next();
- quint64 entryToWriteSize = entryAfterEntryToWrite.first - entryToWrite.first - 1;
- quint64 mapSize = entryAfterEntryToWrite.first - writeOffset - 1;
+ Q_ASSERT( entrySize > 0 ); // MBox entries really cannot have a size <= 0;
- // Now map writeOffSet to entryAfterEntryToWrite offset into mem.
- uchar *memArea = d->mMboxFile.map( writeOffset, mapSize );
+ // we map the whole area of the file starting at the writeOffset up to the
+ // message that have to be moved into memory. This includes eventually the
+ // messages that are the deleted between the first deleted message
+ // encountered and the message that has to be moved.
+ quint64 mapSize = entry.first + entrySize - writeOffset;
- // Now read the entry that must be moved to writeOffset.
- quint64 startOffset = entryToWrite.first - writeOffset;
- char *start = reinterpret_cast<char*>( memArea + startOffset );
- QByteArray entryToWriteData( start, entryToWriteSize );
+ // Now map writeOffSet + mapSize into mem.
+ uchar *memArea = d->mMboxFile.map( writeOffset, mapSize );
- memcpy( memArea, entryToWriteData.constData(), entryToWriteSize );
+ // Now read the entry that must be moved to writeOffset.
+ quint64 startOffset = entry.first - writeOffset;
+ char *start = reinterpret_cast<char*>( memArea + startOffset );
+ QByteArray entryToWriteData( start, entrySize );
- d->mMboxFile.unmap( memArea );
+ memcpy( memArea, entryToWriteData.constData(), entrySize );
- resultingEntryList << MsgInfo( writeOffset, entryToWrite.second );
- writeOffset += entryToWriteSize + 1;
- } else { // entryToWrite is the last entry in the file
- quint64 entryToWriteSize = d->mMboxFile.size() - entryToWrite.first - 1;
- quint64 mapSize = d->mMboxFile.size() - writeOffset - 1;
+ d->mMboxFile.unmap( memArea );
- // Now map writeOffSet upto mapSize into mem.
- uchar *memArea = d->mMboxFile.map( writeOffset, mapSize );
-
- quint64 startOffset = entryToWrite.first - writeOffset;
- char *start = reinterpret_cast<char*>( memArea + startOffset );
- QByteArray entryToWriteData( start, entryToWriteSize );
-
- memcpy( memArea, entryToWriteData.constData(), entryToWriteSize );
-
- d->mMboxFile.unmap( memArea );
-
- resultingEntryList << MsgInfo( writeOffset, entryToWrite.second );
- writeOffset += entryToWriteSize + 1;
-
- // Chop off the remaining bytes.
- d->mMboxFile.resize( writeOffset );
- }
- } else {
- // All entries after writeOffset are marked as deleted so resize the
- // file.
- d->mMboxFile.resize( writeOffset );
- }
- } else {
- // It is the last entry of the file so just chop off the remaining content
- // from writeOffset to end of file.
- d->mMboxFile.resize( writeOffset );
- }
- } else {
resultingEntryList << MsgInfo( writeOffset, entry.second );
+ writeOffset += entrySize + 1;
+ } else if ( !deletedItems.contains( entry.first ) ) {
+ // Unmoved and not deleted entry, can only occure before the first deleted
+ // entry.
+ Q_ASSERT( !writeOffSetInitialized );
+ resultingEntryList << entry;
}
}
+ // Chop off remaining entry bits.
+ d->mMboxFile.resize( writeOffset );
d->mEntries = resultingEntryList;
kDebug() << "Purge comleted successfully, unlocking the file.";
--- trunk/KDE/kdepim/akonadi/resources/mbox/libmbox/tests/mboxtest.cpp #987700:987701
@@ -289,6 +289,65 @@
QCOMPARE( infos2.at( 2 ).first, infos.at( 2 ).first );
}
+void MboxTest::testPurge()
+{
+ MBox mbox1;
+ QVERIFY( mbox1.setLockType( MBox::None ) );
+ QVERIFY( mbox1.load( fileName() ) );
+ mbox1.appendEntry( mMail1 );
+ mbox1.appendEntry( mMail1 );
+ mbox1.appendEntry( mMail1 );
+ QVERIFY( mbox1.save() );
+
+ QList<MsgInfo> list = mbox1.entryList();
+
+ // First test: Delete only the first (all messages afterwards have to be moved).
+ mbox1.purge( QSet<quint64>() << list.first().first );
+
+ MBox mbox2;
+ QVERIFY( mbox2.load( fileName() ) );
+ QList<MsgInfo> list2 = mbox2.entryList();
+ QCOMPARE( list2.size(), 2 ); // Is a message actually gone?
+
+ quint64 newOffsetSecondMessage = list.last().first - list.at( 1 ).first;
+
+ QCOMPARE( list2.first().first, static_cast<quint64>( 0 ) );
+ QCOMPARE( list2.last().first, newOffsetSecondMessage );
+
+ // Second test: Delete the first two (the last message have to be moved).
+ removeTestFile();
+
+ QVERIFY( mbox1.load( fileName() ) );
+ mbox1.appendEntry( mMail1 );
+ mbox1.appendEntry( mMail1 );
+ mbox1.appendEntry( mMail1 );
+ QVERIFY( mbox1.save() );
+
+ list = mbox1.entryList();
+
+ mbox1.purge( QSet<quint64>() << list.at( 0 ).first << list.at( 1 ).first );
+ QVERIFY( mbox2.load( fileName() ) );
+ list2 = mbox2.entryList();
+ QCOMPARE( list2.size(), 1 ); // Are the messages actually gone?
+ QCOMPARE( list2.first().first, static_cast<quint64>( 0 ) );
+
+ // Third test: Delete all messages.
+ removeTestFile();
+
+ QVERIFY( mbox1.load( fileName() ) );
+ mbox1.appendEntry( mMail1 );
+ mbox1.appendEntry( mMail1 );
+ mbox1.appendEntry( mMail1 );
+ QVERIFY( mbox1.save() );
+
+ list = mbox1.entryList();
+
+ mbox1.purge( QSet<quint64>() << list.at( 0 ).first << list.at( 1 ).first << list.at( 2 ).first );
+ QVERIFY( mbox2.load( fileName() ) );
+ list2 = mbox2.entryList();
+ QCOMPARE( list2.size(), 0 ); // Are the messages actually gone?
+}
+
void MboxTest::cleanupTestCase()
{
mTempDir->unlink();
--- trunk/KDE/kdepim/akonadi/resources/mbox/libmbox/tests/mboxtest.h #987700:987701
@@ -39,6 +39,7 @@
void testBlankLines();
void cleanupTestCase();
void testEntries();
+ void testPurge();
private:
QString fileName();
[prev in list] [next in list] [prev in thread] [next in thread]
Configure |
About |
News |
Add a list |
Sponsored by KoreLogic