[prev in list] [next in list] [prev in thread] [next in thread] 

List:       kde-commits
Subject:    [akonadi] /: Introduce concept of database generation
From:       Daniel_Vrátil <dvratil () kde ! org>
Date:       2016-09-30 15:31:23
Message-ID: E1bpzmV-0005ub-GR () code ! kde ! org
[Download RAW message or body]

Git commit d263b9360093b4423c9521cc3e5096581490e3dd by Daniel Vrátil.
Committed on 30/09/2016 at 15:30.
Pushed by dvratil into branch 'master'.

Introduce concept of database generation

Generation is an integer which is guaranteed to never change as long as
the database backend is not removed and re-created. If that happens it
is guaranteed that the new generation identifier will be higher than
the previous one.

Client applications can access it via ServerManager::generation(). The
purpose of the generation number is to make it possible for applications
to detect when the database was recreated and some of their configuration
must be invalidated (e.g. collection IDs stored in config files).

M  +1    -1    CMakeLists.txt
M  +7    -4    autotests/server/fakeakonadiserver.cpp
M  +17   -0    src/core/servermanager.cpp
M  +19   -0    src/core/servermanager.h
M  +2    -0    src/core/servermanager_p.h
M  +3    -0    src/core/session.cpp
M  +21   -15   src/private/protocol.cpp
M  +3    -1    src/private/protocol_p.h
M  +8    -3    src/server/connection.cpp
M  +8    -3    src/server/notificationsubscriber.cpp
M  +2    -1    src/server/storage/akonadidb.xml
M  +10   -1    src/server/storage/dbinitializer.cpp

http://commits.kde.org/akonadi/d263b9360093b4423c9521cc3e5096581490e3dd

diff --git a/CMakeLists.txt b/CMakeLists.txt
index ce22d1d..d9381d8 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -22,7 +22,7 @@ include(CheckSymbolExists)
 
 include(AkonadiMacros)
 
-set(PIM_VERSION "5.3.45")
+set(PIM_VERSION "5.3.46")
 
 set(QT_REQUIRED_VERSION "5.6.0")
 set(AKONADI_VERSION ${PIM_VERSION})
diff --git a/autotests/server/fakeakonadiserver.cpp \
b/autotests/server/fakeakonadiserver.cpp index 9d0f717..420a0e7 100644
--- a/autotests/server/fakeakonadiserver.cpp
+++ b/autotests/server/fakeakonadiserver.cpp
@@ -147,11 +147,14 @@ QString FakeAkonadiServer::instanceName()
 
 TestScenario::List FakeAkonadiServer::loginScenario(const QByteArray &sessionId)
 {
+    Protocol::HelloResponse hello;
+    hello.setServerName(QStringLiteral("Akonadi"));
+    hello.setMessage(QStringLiteral("Not really IMAP server"));
+    hello.setProtocolVersion(Protocol::version());
+    hello.setGeneration(1);
+
     return {
-        TestScenario::create(0, TestScenario::ServerCmd,
-                             Protocol::HelloResponse(QStringLiteral("Akonadi"),
-                                                     QStringLiteral("Not Really IMAP \
                server"),
-                                                     Protocol::version())),
+        TestScenario::create(0, TestScenario::ServerCmd, hello),
         TestScenario::create(1,TestScenario::ClientCmd,
                              Protocol::LoginCommand(sessionId.isEmpty() ? \
instanceName().toLatin1() : sessionId)),  TestScenario::create(1, \
                TestScenario::ServerCmd,
diff --git a/src/core/servermanager.cpp b/src/core/servermanager.cpp
index 219a7df..f078553 100644
--- a/src/core/servermanager.cpp
+++ b/src/core/servermanager.cpp
@@ -118,6 +118,7 @@ public:
 
     ServerManager *instance;
     static int serverProtocolVersion;
+    static uint generation;
     ServerManager::State mState;
     QScopedPointer<QTimer> mSafetyTimer;
     Firstrun *mFirstRunner;
@@ -125,6 +126,7 @@ public:
 };
 
 int ServerManagerPrivate::serverProtocolVersion = -1;
+uint ServerManagerPrivate::generation = 0;
 Internal::ClientType ServerManagerPrivate::clientType = Internal::User;
 
 Q_GLOBAL_STATIC(ServerManagerPrivate, sInstance)
@@ -351,6 +353,11 @@ QString ServerManager::addNamespace(const QString &string)
     return string;
 }
 
+uint ServerManager::generation()
+{
+    return Internal::generation();
+}
+
 int Internal::serverProtocolVersion()
 {
     return ServerManagerPrivate::serverProtocolVersion;
@@ -364,6 +371,16 @@ void Internal::setServerProtocolVersion(int version)
     }
 }
 
+uint Internal::generation()
+{
+    return ServerManagerPrivate::generation;
+}
+
+void Internal::setGeneration(uint generation)
+{
+    ServerManagerPrivate::generation = generation;
+}
+
 Internal::ClientType Internal::clientType()
 {
     return ServerManagerPrivate::clientType;
diff --git a/src/core/servermanager.h b/src/core/servermanager.h
index 282892e..8031d1d 100644
--- a/src/core/servermanager.h
+++ b/src/core/servermanager.h
@@ -178,6 +178,25 @@ public:
      */
     static QString agentConfigFilePath(const QString &identifier);
 
+    /**
+     * Returns current Akonadi database generation identifier
+     *
+     * Generation is guaranteed to never change unless as long as the database
+     * backend is not removed and re-created. In such case it is guaranteed that
+     * the new generation number will be higher than the previous one.
+     *
+     * Generation can be used by applications to detect when Akonadi database
+     * has been recreated and thus some of the configuration (for example
+     * collection IDs stored in a config file) must be invalidated.
+     *
+     * @note Note that the generation number is only available if the server
+     * is running. If this function is called before the server starts it will
+     * return 0.
+     *
+     * @since 5.4
+     */
+    static uint generation();
+
 Q_SIGNALS:
     /**
      * Emitted whenever the server becomes fully operational.
diff --git a/src/core/servermanager_p.h b/src/core/servermanager_p.h
index 85f17b6..370d252 100644
--- a/src/core/servermanager_p.h
+++ b/src/core/servermanager_p.h
@@ -32,6 +32,8 @@ namespace Internal
 
 AKONADICORE_EXPORT int serverProtocolVersion();
 AKONADICORE_EXPORT void setServerProtocolVersion(int version);
+AKONADICORE_EXPORT uint generation();
+AKONADICORE_EXPORT void setGeneration(uint generation);
 
 enum ClientType {
     User,
diff --git a/src/core/session.cpp b/src/core/session.cpp
index 7545acc..6a96668 100644
--- a/src/core/session.cpp
+++ b/src/core/session.cpp
@@ -111,11 +111,14 @@ bool SessionPrivate::handleCommand(qint64 tag, const \
Protocol::Command &cmd)  }
 
         qCDebug(AKONADICORE_LOG) << "Connected to" << hello.serverName() << ", using \
protocol version" << hello.protocolVersion(); +        qCDebug(AKONADICORE_LOG) << \
"Server generation:" << hello.generation();  qCDebug(AKONADICORE_LOG) << "Server \
                says:" << hello.message();
         // Version mismatch is handled in SessionPrivate::startJob() so that
         // we can report the error out via KJob API
         protocolVersion = hello.protocolVersion();
         Internal::setServerProtocolVersion(protocolVersion);
+        Internal::setGeneration(hello.generation());
+
 
         Protocol::LoginCommand login(sessionId);
         sendCommand(nextTag(), login);
diff --git a/src/private/protocol.cpp b/src/private/protocol.cpp
index 3597879..ecb7cb0 100644
--- a/src/private/protocol.cpp
+++ b/src/private/protocol.cpp
@@ -49,7 +49,7 @@ namespace Akonadi {
 namespace Protocol {
 
 int version() {
-    return 55;
+    return 56;
 }
 
 }
@@ -1533,12 +1533,7 @@ public:
     HelloResponsePrivate()
         : ResponsePrivate(Command::Hello)
         , protocol(0)
-    {}
-    HelloResponsePrivate(const QString &server, const QString &message, int \
                protocol)
-        : ResponsePrivate(Command::Hello)
-        , server(server)
-        , message(message)
-        , protocol(protocol)
+        , generation(0)
     {}
 
     HelloResponsePrivate(const HelloResponsePrivate &other)
@@ -1546,6 +1541,7 @@ public:
         , server(other.server)
         , message(other.message)
         , protocol(other.protocol)
+        , generation(other.generation)
     {}
 
     bool compare(const CommandPrivate *other) const Q_DECL_OVERRIDE
@@ -1553,7 +1549,8 @@ public:
         return ResponsePrivate::compare(other)
             && COMPARE(server)
             && COMPARE(message)
-            && COMPARE(protocol);
+            && COMPARE(protocol)
+            && COMPARE(generation);
     }
 
     DataStream &serialize(DataStream &stream) const Q_DECL_OVERRIDE
@@ -1561,7 +1558,8 @@ public:
         return ResponsePrivate::serialize(stream)
                << server
                << message
-               << protocol;
+               << protocol
+               << generation;
     }
 
     DataStream &deserialize(DataStream &stream) Q_DECL_OVERRIDE
@@ -1569,7 +1567,8 @@ public:
         return ResponsePrivate::deserialize(stream)
                >> server
                >> message
-               >> protocol;
+               >> protocol
+               >> generation;
     }
 
     void debugString(DebugBlock &blck) const Q_DECL_OVERRIDE
@@ -1578,6 +1577,7 @@ public:
         blck.write("Server", server);
         blck.write("Protocol Version", protocol);
         blck.write("Message", message);
+        blck.write("Generation", generation);
     }
 
     CommandPrivate *clone() const Q_DECL_OVERRIDE
@@ -1588,6 +1588,7 @@ public:
     QString server;
     QString message;
     int protocol;
+    uint generation;
 };
 
 
@@ -1602,11 +1603,6 @@ public:
 
 AKONADI_DECLARE_PRIVATE(HelloResponse)
 
-HelloResponse::HelloResponse(const QString &server, const QString &message, int \
                protocol)
-    : Response(new HelloResponsePrivate(server, message, protocol))
-{
-}
-
 HelloResponse::HelloResponse()
     : Response(new HelloResponsePrivate)
 {
@@ -1648,6 +1644,16 @@ int HelloResponse::protocolVersion() const
     return d_func()->protocol;
 }
 
+void HelloResponse::setGeneration(uint generation)
+{
+    d_func()->generation = generation;
+}
+
+uint HelloResponse::generation() const
+{
+    return d_func()->generation;
+}
+
 DataStream &operator<<(DataStream &stream, const HelloResponse &command)
 {
     return command.d_func()->serialize(stream);
diff --git a/src/private/protocol_p.h b/src/private/protocol_p.h
index 97ec4ef..4da44cc 100644
--- a/src/private/protocol_p.h
+++ b/src/private/protocol_p.h
@@ -476,7 +476,6 @@ class AKONADIPRIVATE_EXPORT HelloResponse : public Response
 public:
     explicit HelloResponse();
     explicit HelloResponse(const Command &command);
-    HelloResponse(const QString &server, const QString &message, int protocol);
 
     void setServerName(const QString &server);
     QString serverName() const;
@@ -487,6 +486,9 @@ public:
     void setProtocolVersion(int protocolVersion);
     int protocolVersion() const;
 
+    void setGeneration(uint generation);
+    uint generation() const;
+
 private:
     AKONADI_DECLARE_PRIVATE(HelloResponse)
 
diff --git a/src/server/connection.cpp b/src/server/connection.cpp
index 0344107..a77d1e4 100644
--- a/src/server/connection.cpp
+++ b/src/server/connection.cpp
@@ -121,9 +121,14 @@ void Connection::quit()
 
 void Connection::slotSendHello()
 {
-    sendResponse(0, Protocol::HelloResponse(QStringLiteral("Akonadi"),
-                                            QStringLiteral("Not Really IMAP \
                server"),
-                                            Protocol::version()));
+    SchemaVersion version = SchemaVersion::retrieveAll().first();
+
+    Protocol::HelloResponse hello;
+    hello.setServerName(QStringLiteral("Akonadi"));
+    hello.setMessage(QStringLiteral("Not Really IMAP server"));
+    hello.setProtocolVersion(Protocol::version());
+    hello.setGeneration(version.generation());
+    sendResponse(0, hello);
 }
 
 DataStore *Connection::storageBackend()
diff --git a/src/server/notificationsubscriber.cpp \
b/src/server/notificationsubscriber.cpp index ca33c96..ed5d348 100644
--- a/src/server/notificationsubscriber.cpp
+++ b/src/server/notificationsubscriber.cpp
@@ -58,9 +58,14 @@ NotificationSubscriber::NotificationSubscriber(NotificationManager \
*manager, qui  this, &NotificationSubscriber::socketDisconnected);
     mSocket->setSocketDescriptor(socketDescriptor);
 
-    writeCommand(0, Protocol::HelloResponse(QStringLiteral("Akonadi"),
-                                                        QStringLiteral("Not-really \
                IMAP server"),
-                                                        Protocol::version()));
+    const SchemaVersion schema = SchemaVersion::retrieveAll().first();
+
+    Protocol::HelloResponse hello;
+    hello.setServerName(QStringLiteral("Akonadi"));
+    hello.setMessage(QStringLiteral("Not really IMAP server"));
+    hello.setProtocolVersion(Protocol::version());
+    hello.setGeneration(schema.generation());
+    writeCommand(0, hello);
 }
 
 NotificationSubscriber::~NotificationSubscriber()
diff --git a/src/server/storage/akonadidb.xml b/src/server/storage/akonadidb.xml
index ed71af9..a3646ee 100644
--- a/src/server/storage/akonadidb.xml
+++ b/src/server/storage/akonadidb.xml
@@ -66,7 +66,8 @@
   <table name="SchemaVersion">
     <comment>Contains the schema version of the database.</comment>
     <column name="version" type="int" default="0" allowNull="false"/>
-    <data columns="version" values="33"/>
+    <column name="generation" type="int" default="0" allowNull="false" />
+    <data columns="version" values="34"/>
   </table>
 
   <table name="Resource">
diff --git a/src/server/storage/dbinitializer.cpp \
b/src/server/storage/dbinitializer.cpp index 572ee53..f2d840a 100644
--- a/src/server/storage/dbinitializer.cpp
+++ b/src/server/storage/dbinitializer.cpp
@@ -23,7 +23,7 @@
 #include "querybuilder.h"
 #include "dbexception.h"
 #include "schema.h"
-#include "entity.h"
+#include "entities.h"
 #include "akonadiserver_debug.h"
 
 #include <QtCore/QFile>
@@ -92,6 +92,15 @@ bool DbInitializer::run()
             }
         }
 
+        // Now finally check and set the generation identifier if necessary
+        SchemaVersion version = SchemaVersion::retrieveAll().first();
+        if (version.generation() == 0) {
+            version.setGeneration(QDateTime::currentDateTimeUtc().toTime_t());
+            version.update();
+
+            qCDebug(AKONADISERVER_LOG) << "Generation:" << version.generation();
+        }
+
         qCDebug(AKONADISERVER_LOG) << "DbInitializer::run() done";
         return true;
     } catch (const DbException &e) {


[prev in list] [next in list] [prev in thread] [next in thread] 

Configure | About | News | Add a list | Sponsored by KoreLogic