Rex Dieter 8b4426d
From 9c0dc6b3f0826d32eac310b2e7ecd858ca3df681 Mon Sep 17 00:00:00 2001
Rex Dieter 8b4426d
From: =?UTF-8?q?Dan=20Vr=C3=A1til?= <dvratil@redhat.com>
Rex Dieter 8b4426d
Date: Mon, 29 Jun 2015 22:45:11 +0200
Rex Dieter 8b4426d
Subject: [PATCH 33/34] Don't leak old external payload files
Dan Vrátil 62a3cba
Rex Dieter 8b4426d
Actually delete old payload files after we increase the payload revision or
Rex Dieter 8b4426d
switch from external to internal payload. This caused ~/.local/share/akonadi/file_db_data
Rex Dieter 8b4426d
to grow insanely for all users, leaving them with many duplicated files (just with
Rex Dieter 8b4426d
different revisions).
Rex Dieter 8b4426d
Rex Dieter 8b4426d
It is recommended that users run akonadictl fsck to clean up the leaked payload
Rex Dieter 8b4426d
files.
Rex Dieter 8b4426d
Rex Dieter 8b4426d
Note that there won't be any more releases of Akonadi 1.13 (and this has been
Rex Dieter 8b4426d
fixed in master already), so I strongly recommend distributions to pick this
Rex Dieter 8b4426d
patch into their packaging.
Rex Dieter 8b4426d
Rex Dieter 8b4426d
BUG: 341884
Rex Dieter 8b4426d
CCBUG: 338402
Rex Dieter 8b4426d
---
Rex Dieter 8b4426d
 server/src/storage/partstreamer.cpp        | 14 ++++++++++++++
Rex Dieter 8b4426d
 server/tests/unittest/partstreamertest.cpp | 24 +++++++++++++-----------
Rex Dieter 8b4426d
 2 files changed, 27 insertions(+), 11 deletions(-)
Dan Vrátil 62a3cba
Dan Vrátil 62a3cba
diff --git a/server/src/storage/partstreamer.cpp b/server/src/storage/partstreamer.cpp
Dan Vrátil 62a3cba
index 2ec41fa..71bdca8 100644
Dan Vrátil 62a3cba
--- a/server/src/storage/partstreamer.cpp
Dan Vrátil 62a3cba
+++ b/server/src/storage/partstreamer.cpp
Dan Vrátil 62a3cba
@@ -290,6 +290,12 @@ bool PartStreamer::stream(const QByteArray &command, bool checkExists,
Dan Vrátil 62a3cba
         mDataChanged = true;
Dan Vrátil 62a3cba
     }
Dan Vrátil 62a3cba
 
Dan Vrátil 62a3cba
+    // If the part is external, remember it's current file name
Dan Vrátil 62a3cba
+    QString originalFile;
Dan Vrátil 62a3cba
+    if (part.isValid() && part.external()) {
Dan Vrátil 62a3cba
+        originalFile = PartHelper::resolveAbsolutePath(part.data());
Dan Vrátil 62a3cba
+    }
Dan Vrátil 62a3cba
+
Dan Vrátil 62a3cba
     part.setPartType(partType);
Dan Vrátil 62a3cba
     part.setVersion(partVersion);
Dan Vrátil 62a3cba
     part.setPimItemId(mItem.id());
Dan Vrátil 62a3cba
@@ -306,6 +312,14 @@ bool PartStreamer::stream(const QByteArray &command, bool checkExists,
Dan Vrátil 62a3cba
         *changed = mDataChanged;
Dan Vrátil 62a3cba
     }
Dan Vrátil 62a3cba
 
Dan Vrátil 62a3cba
+    if (!originalFile.isEmpty()) {
Dan Vrátil 62a3cba
+        // If the part was external but is not anymore, or if it's still external
Dan Vrátil 62a3cba
+        // but the filename has changed (revision update), remove the original file
Dan Vrátil 62a3cba
+        if (!part.external() || (part.external() && originalFile != PartHelper::resolveAbsolutePath(part.data()))) {
Dan Vrátil 62a3cba
+            PartHelper::removeFile(originalFile);
Dan Vrátil 62a3cba
+        }
Dan Vrátil 62a3cba
+    }
Dan Vrátil 62a3cba
+
Dan Vrátil 62a3cba
     return ok;
Dan Vrátil 62a3cba
 }
Dan Vrátil 62a3cba
 
Dan Vrátil 62a3cba
diff --git a/server/tests/unittest/partstreamertest.cpp b/server/tests/unittest/partstreamertest.cpp
Dan Vrátil 62a3cba
index 05e3a8a..669bbbc 100644
Dan Vrátil 62a3cba
--- a/server/tests/unittest/partstreamertest.cpp
Dan Vrátil 62a3cba
+++ b/server/tests/unittest/partstreamertest.cpp
Dan Vrátil 62a3cba
@@ -91,6 +91,7 @@ private Q_SLOTS:
Dan Vrátil 62a3cba
         QTest::addColumn<qint64>("expectedPartSize");
Dan Vrátil 62a3cba
         QTest::addColumn<bool>("expectedChanged");
Dan Vrátil 62a3cba
         QTest::addColumn<bool>("isExternal");
Dan Vrátil 62a3cba
+        QTest::addColumn<int>("version");
Dan Vrátil 62a3cba
         QTest::addColumn<PimItem>("pimItem");
Dan Vrátil 62a3cba
 
Dan Vrátil 62a3cba
         PimItem item;
Dan Vrátil 62a3cba
@@ -101,22 +102,22 @@ private Q_SLOTS:
Dan Vrátil 62a3cba
         QVERIFY(item.insert());
Dan Vrátil 62a3cba
 
Dan Vrátil 62a3cba
         // Order of these tests matters!
Dan Vrátil 62a3cba
-        QTest::newRow("item 1, internal") << QByteArray("PLD:DATA") << QByteArray("123") << 3ll << true << false << item;
Dan Vrátil 62a3cba
-        QTest::newRow("item 1, change to external") << QByteArray("PLD:DATA") << QByteArray("123456789") << 9ll << true << true << item;
Dan Vrátil 62a3cba
-        QTest::newRow("item 1, update external") << QByteArray("PLD:DATA") << QByteArray("987654321") << 9ll << true << true << item;
Dan Vrátil 62a3cba
-        QTest::newRow("item 1, external, no change") << QByteArray("PLD:DATA") << QByteArray("987654321") << 9ll << false << true << item;
Dan Vrátil 62a3cba
-        QTest::newRow("item 1, change to internal") << QByteArray("PLD:DATA") << QByteArray("1234") << 4ll << true << false << item;
Dan Vrátil 62a3cba
-        QTest::newRow("item 1, internal, no change") << QByteArray("PLD:DATA") << QByteArray("1234") << 4ll << false << false << item;
Dan Vrátil 62a3cba
+        QTest::newRow("item 1, internal") << QByteArray("PLD:DATA") << QByteArray("123") << 3ll << true << false << -1 << item;
Dan Vrátil 62a3cba
+        QTest::newRow("item 1, change to external") << QByteArray("PLD:DATA") << QByteArray("123456789") << 9ll << true << true << 0 << item;
Dan Vrátil 62a3cba
+        QTest::newRow("item 1, update external") << QByteArray("PLD:DATA") << QByteArray("987654321") << 9ll << true << true << 1 << item;
Dan Vrátil 62a3cba
+        QTest::newRow("item 1, external, no change") << QByteArray("PLD:DATA") << QByteArray("987654321") << 9ll << false << true << 2 << item;
Dan Vrátil 62a3cba
+        QTest::newRow("item 1, change to internal") << QByteArray("PLD:DATA") << QByteArray("1234") << 4ll << true << false << 2 << item;
Dan Vrátil 62a3cba
+        QTest::newRow("item 1, internal, no change") << QByteArray("PLD:DATA") << QByteArray("1234") << 4ll << false << false << 2 << item;
Dan Vrátil 62a3cba
     }
Dan Vrátil 62a3cba
 
Dan Vrátil 62a3cba
     void testStreamer()
Dan Vrátil 62a3cba
     {
Dan Vrátil 62a3cba
-        return;
Dan Vrátil 62a3cba
         QFETCH(QByteArray, expectedPartName);
Dan Vrátil 62a3cba
         QFETCH(QByteArray, expectedData);
Dan Vrátil 62a3cba
         QFETCH(qint64, expectedPartSize);
Dan Vrátil 62a3cba
         QFETCH(bool, expectedChanged);
Dan Vrátil 62a3cba
         QFETCH(bool, isExternal);
Dan Vrátil 62a3cba
+        QFETCH(int, version);
Dan Vrátil 62a3cba
         QFETCH(PimItem, pimItem);
Dan Vrátil 62a3cba
 
Dan Vrátil 62a3cba
         FakeConnection connection;
Dan Vrátil 62a3cba
@@ -160,17 +161,18 @@ private Q_SLOTS:
Dan Vrátil 62a3cba
 
Dan Vrátil 62a3cba
         PimItem item = PimItem::retrieveById(pimItem.id());
Dan Vrátil 62a3cba
         const QVector<Part> parts = item.parts();
Dan Vrátil 62a3cba
-        QVERIFY(parts.count() == 1);
Dan Vrátil 62a3cba
+        QCOMPARE(parts.count(), 1);
Dan Vrátil 62a3cba
         const Part part = parts[0];
Dan Vrátil 62a3cba
         QCOMPARE(part.datasize(), expectedPartSize);
Dan Vrátil 62a3cba
         QCOMPARE(part.external(), isExternal);
Dan Vrátil 62a3cba
+        qDebug() << part.version() << part.data();
Dan Vrátil 62a3cba
         const QByteArray data = part.data();
Dan Vrátil 62a3cba
         if (isExternal) {
Dan Vrátil 62a3cba
             QVERIFY(streamerSpy.count() == 1);
Dan Vrátil 62a3cba
             QVERIFY(streamerSpy.first().count() == 1);
Dan Vrátil 62a3cba
             const Response response = streamerSpy.first().first().value<Akonadi::Server::Response>();
Dan Vrátil 62a3cba
             const QByteArray str = response.asString();
Dan Vrátil 62a3cba
-            const QByteArray expectedResponse = "+ STREAM [FILE " + QByteArray::number(part.id()) + "_r" + QByteArray::number(part.version()) + "]";
Dan Vrátil 62a3cba
+            const QByteArray expectedResponse = "+ STREAM [FILE " + QByteArray::number(part.id()) + "_r" + QByteArray::number(version) + "]";
Dan Vrátil 62a3cba
             QCOMPARE(QString::fromUtf8(str), QString::fromUtf8(expectedResponse));
Dan Vrátil 62a3cba
 
Dan Vrátil 62a3cba
             QFile file(PartHelper::resolveAbsolutePath(data));
Dan Vrátil 62a3cba
@@ -182,7 +184,7 @@ private Q_SLOTS:
Dan Vrátil 62a3cba
             QCOMPARE(fileData, expectedData);
Dan Vrátil 62a3cba
 
Dan Vrátil 62a3cba
             // Make sure no previous versions are left behind in file_db_data
Dan Vrátil 62a3cba
-            for (int i = 0; i < part.version(); ++i) {
Dan Vrátil 62a3cba
+            for (int i = 0; i < version; ++i) {
Dan Vrátil 62a3cba
                 const QByteArray fileName = QByteArray::number(part.id()) + "_r" + QByteArray::number(part.version());
Dan Vrátil 62a3cba
                 const QString filePath = PartHelper::resolveAbsolutePath(fileName);
Dan Vrátil 62a3cba
                 QVERIFY(!QFile::exists(filePath));
Dan Vrátil 62a3cba
@@ -194,7 +196,7 @@ private Q_SLOTS:
Dan Vrátil 62a3cba
             QCOMPARE(data, expectedData);
Dan Vrátil 62a3cba
 
Dan Vrátil 62a3cba
             // Make sure nothing is left behind in file_db_data
Dan Vrátil 62a3cba
-            for (int i = 0; i <= part.version(); ++i) {
Dan Vrátil 62a3cba
+            for (int i = 0; i <= version; ++i) {
Dan Vrátil 62a3cba
                 const QByteArray fileName = QByteArray::number(part.id()) + "_r" + QByteArray::number(part.version());
Dan Vrátil 62a3cba
                 const QString filePath = PartHelper::resolveAbsolutePath(fileName);
Dan Vrátil 62a3cba
                 QVERIFY(!QFile::exists(filePath));
Rex Dieter 8b4426d
-- 
Rex Dieter 8b4426d
2.4.3
Rex Dieter 8b4426d