[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-19 12:42:39
Message-ID: 1245415359.738457.31035.nullmailer () svn ! kde ! org
[Download RAW message or body]
SVN commit 983908 by bbroeksema:
First try on the purge method. Needs testing, so don't use it yet.
M +117 -2 mbox.cpp
M +17 -0 mbox.h
--- trunk/KDE/kdepim/akonadi/resources/mbox/libmbox/mbox.cpp #983907:983908
@@ -74,6 +74,8 @@
bool mReadOnly;
};
+static QString sMBoxSeperatorRegExp( "^From .*[0-9][0-9]:[0-9][0-9]" );
+
/// private static methods.
QByteArray quoteAndEncode(const QString &str)
@@ -182,7 +184,7 @@
d->mAppendedEntries.clear();
d->mEntries.clear();
- QRegExp regexp("^From .*[0-9][0-9]:[0-9][0-9]");
+ QRegExp regexp( sMBoxSeperatorRegExp );
QByteArray line;
QByteArray prevSeparator;
quint64 offs = 0; // The offset of the next message to read.
@@ -313,6 +315,119 @@
return d->mFileLocked;
}
+static bool lessThanByOffset( const MsgInfo &left, const MsgInfo &right )
+{
+ return left.first < right.first;
+}
+
+bool MBox::purge( const QSet<quint64> &deletedItems )
+{
+ if ( d->mMboxFile.fileName().isEmpty() )
+ return false; // No file loaded yet.
+
+ if ( deletedItems.isEmpty() )
+ return true; // Nothing to do.
+
+ if ( !lock() )
+ return false;
+
+ foreach ( quint64 offset, deletedItems ) {
+ d->mMboxFile.seek( offset );
+ QByteArray line = d->mMboxFile.readLine();
+ QRegExp regexp( sMBoxSeperatorRegExp );
+
+ if ( regexp.indexIn(line) < 0 ) {
+ unlock();
+ return false; // The file is messed up or the index is incorrect.
+ }
+ }
+
+ qSort( d->mEntries.begin(), d->mEntries.end(), lessThanByOffset );
+ quint64 writeOffset = 0;
+ QList<MsgInfo> resultingEntryList;
+
+ 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.
+ writeOffset = entry.first;
+
+ 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;
+ }
+
+ 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;
+
+ // Now map writeOffSet to entryAfterEntryToWrite offset into mem.
+ uchar *memArea = d->mMboxFile.map( writeOffset, mapSize );
+
+ // 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 );
+
+ memcpy( memArea, entryToWriteData.constData(), entryToWriteSize );
+
+ d->mMboxFile.unmap( memArea );
+
+ 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;
+
+ // 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 );
+ }
+ }
+
+ d->mEntries = resultingEntryList;
+
+ kDebug() << "Purge comleted successfully, unlocking the file.";
+ return unlock(); // FIXME: What if this fails? It will return false but the
+ // file has changed.
+}
+
KMime::Message *MBox::readEntry(quint64 offset)
{
bool wasLocked = d->mFileLocked;
@@ -334,7 +449,7 @@
d->mMboxFile.seek(offset);
QByteArray line = d->mMboxFile.readLine();
- QRegExp regexp("^From .*[0-9][0-9]:[0-9][0-9]");
+ QRegExp regexp( sMBoxSeperatorRegExp );
if (regexp.indexIn(line) < 0) {
unlock();
--- trunk/KDE/kdepim/akonadi/resources/mbox/libmbox/mbox.h #983907:983908
@@ -100,6 +100,23 @@
bool lock();
/**
+ * Removes all messages at given offsets from the current reference file
+ * (i.e. the file that is loaded with load( const QString & ) or the file
+ * from the last save( const QString & ) call if that was not the same file).
+ * This method will first check if all lines at the offsets are actually
+ * seperator lines if this is not the no message will be deleted to prevent
+ * corruption.
+ *
+ * @param deletedItems Offsets of the messages that should be removed from
+ * the file.
+ *
+ * @return true if all offsets refer to a mbox seperator line and a file was
+ * loaded, false otherewhise. In the latter the physical file has
+ * not changed.
+ */
+ bool purge( const QSet<quint64> &deletedItems );
+
+ /**
* Reads the entire message from the file at given @param offset. If the
* mbox file is not locked this method will lock the file before reading and
* unlock it after reading. If the file already is locked, it will not
[prev in list] [next in list] [prev in thread] [next in thread]
Configure |
About |
News |
Add a list |
Sponsored by KoreLogic