Sync last message id per buffer
authorJanne Koschinski <janne@kuschku.de>
Thu, 30 May 2019 06:39:06 +0000 (08:39 +0200)
committerManuel Nickschas <sputnick@quassel-irc.org>
Sun, 15 Mar 2020 16:26:24 +0000 (17:26 +0100)
src/common/buffersyncer.cpp
src/common/buffersyncer.h
src/core/SQL/PostgreSQL/select_buffer_last_messages.sql [new file with mode: 0644]
src/core/SQL/SQLite/select_buffer_last_messages.sql [new file with mode: 0644]
src/core/core.h
src/core/corebuffersyncer.cpp
src/core/postgresqlstorage.cpp
src/core/postgresqlstorage.h
src/core/sqlitestorage.cpp
src/core/sqlitestorage.h
src/core/storage.h

index cbebd03..74126a1 100644 (file)
@@ -26,18 +26,25 @@ BufferSyncer::BufferSyncer(QObject* parent)
     : SyncableObject(parent)
 {}
 
     : SyncableObject(parent)
 {}
 
-BufferSyncer::BufferSyncer(QHash<BufferId, MsgId> lastSeenMsg,
+BufferSyncer::BufferSyncer(QHash<BufferId, MsgId> lastMsg,
+                           QHash<BufferId, MsgId> lastSeenMsg,
                            QHash<BufferId, MsgId> markerLines,
                            QHash<BufferId, Message::Types> activities,
                            QHash<BufferId, int> highlightCounts,
                            QObject* parent)
     : SyncableObject(parent)
                            QHash<BufferId, MsgId> markerLines,
                            QHash<BufferId, Message::Types> activities,
                            QHash<BufferId, int> highlightCounts,
                            QObject* parent)
     : SyncableObject(parent)
+    , _lastMsg(std::move(lastMsg))
     , _lastSeenMsg(std::move(lastSeenMsg))
     , _markerLines(std::move(markerLines))
     , _bufferActivities(std::move(activities))
     , _highlightCounts(std::move(highlightCounts))
 {}
 
     , _lastSeenMsg(std::move(lastSeenMsg))
     , _markerLines(std::move(markerLines))
     , _bufferActivities(std::move(activities))
     , _highlightCounts(std::move(highlightCounts))
 {}
 
+MsgId BufferSyncer::lastMsg(BufferId buffer) const
+{
+    return _lastMsg.value(buffer, MsgId());
+}
+
 MsgId BufferSyncer::lastSeenMsg(BufferId buffer) const
 {
     return _lastSeenMsg.value(buffer, MsgId());
 MsgId BufferSyncer::lastSeenMsg(BufferId buffer) const
 {
     return _lastSeenMsg.value(buffer, MsgId());
@@ -77,6 +84,26 @@ bool BufferSyncer::setMarkerLine(BufferId buffer, const MsgId& msgId)
     return true;
 }
 
     return true;
 }
 
+QVariantList BufferSyncer::initLastMsg() const
+{
+    QVariantList list;
+    QHash<BufferId, MsgId>::const_iterator iter = _lastMsg.constBegin();
+    while (iter != _lastMsg.constEnd()) {
+        list << QVariant::fromValue<BufferId>(iter.key()) << QVariant::fromValue<MsgId>(iter.value());
+        ++iter;
+    }
+    return list;
+}
+
+void BufferSyncer::initSetLastMsg(const QVariantList& list)
+{
+    _lastMsg.clear();
+    Q_ASSERT(list.count() % 2 == 0);
+    for (int i = 0; i < list.count(); i += 2) {
+        setLastMsg(list.at(i).value<BufferId>(), list.at(i + 1).value<MsgId>());
+    }
+}
+
 QVariantList BufferSyncer::initLastSeenMsg() const
 {
     QVariantList list;
 QVariantList BufferSyncer::initLastSeenMsg() const
 {
     QVariantList list;
@@ -144,6 +171,8 @@ Message::Types BufferSyncer::activity(BufferId buffer) const
 
 void BufferSyncer::removeBuffer(BufferId buffer)
 {
 
 void BufferSyncer::removeBuffer(BufferId buffer)
 {
+    if (_lastMsg.contains(buffer))
+        _lastMsg.remove(buffer);
     if (_lastSeenMsg.contains(buffer))
         _lastSeenMsg.remove(buffer);
     if (_markerLines.contains(buffer))
     if (_lastSeenMsg.contains(buffer))
         _lastSeenMsg.remove(buffer);
     if (_markerLines.contains(buffer))
@@ -158,9 +187,12 @@ void BufferSyncer::removeBuffer(BufferId buffer)
 
 void BufferSyncer::mergeBuffersPermanently(BufferId buffer1, BufferId buffer2)
 {
 
 void BufferSyncer::mergeBuffersPermanently(BufferId buffer1, BufferId buffer2)
 {
+    setLastMsg(buffer1, std::max(_lastMsg[buffer1], _lastMsg[buffer2]));
     setBufferActivity(buffer1, _bufferActivities[buffer1] | _bufferActivities[buffer2]);
     setHighlightCount(buffer1, _highlightCounts[buffer1] + _highlightCounts[buffer2]);
 
     setBufferActivity(buffer1, _bufferActivities[buffer1] | _bufferActivities[buffer2]);
     setHighlightCount(buffer1, _highlightCounts[buffer1] + _highlightCounts[buffer2]);
 
+    if (_lastMsg.contains(buffer2))
+        _lastMsg.remove(buffer2);
     if (_lastSeenMsg.contains(buffer2))
         _lastSeenMsg.remove(buffer2);
     if (_markerLines.contains(buffer2))
     if (_lastSeenMsg.contains(buffer2))
         _lastSeenMsg.remove(buffer2);
     if (_markerLines.contains(buffer2))
index 4bca34e..d6535e2 100644 (file)
@@ -33,13 +33,15 @@ class COMMON_EXPORT BufferSyncer : public SyncableObject
 
 public:
     explicit BufferSyncer(QObject* parent);
 
 public:
     explicit BufferSyncer(QObject* parent);
-    explicit BufferSyncer(QHash<BufferId, MsgId> lastSeenMsg,
+    explicit BufferSyncer(QHash<BufferId, MsgId> lastMsg,
+                          QHash<BufferId, MsgId> lastSeenMsg,
                           QHash<BufferId, MsgId> markerLines,
                           QHash<BufferId, Message::Types> activities,
                           QHash<BufferId, int> highlightCounts,
                           QObject* parent);
 
     MsgId lastSeenMsg(BufferId buffer) const;
                           QHash<BufferId, MsgId> markerLines,
                           QHash<BufferId, Message::Types> activities,
                           QHash<BufferId, int> highlightCounts,
                           QObject* parent);
 
     MsgId lastSeenMsg(BufferId buffer) const;
+    MsgId lastMsg(BufferId buffer) const;
     MsgId markerLine(BufferId buffer) const;
     Message::Types activity(BufferId buffer) const;
     int highlightCount(BufferId buffer) const;
     MsgId markerLine(BufferId buffer) const;
     Message::Types activity(BufferId buffer) const;
     int highlightCount(BufferId buffer) const;
@@ -59,6 +61,9 @@ public:
     }
 
 public slots:
     }
 
 public slots:
+    QVariantList initLastMsg() const;
+    void initSetLastMsg(const QVariantList&);
+
     QVariantList initLastSeenMsg() const;
     void initSetLastSeenMsg(const QVariantList&);
 
     QVariantList initLastSeenMsg() const;
     void initSetLastSeenMsg(const QVariantList&);
 
@@ -71,6 +76,13 @@ public slots:
     QVariantList initHighlightCounts() const;
     void initSetHighlightCounts(const QVariantList&);
 
     QVariantList initHighlightCounts() const;
     void initSetHighlightCounts(const QVariantList&);
 
+    virtual inline void setLastMsg(BufferId buffer, const MsgId& msgId)
+    {
+        SYNC(ARG(buffer), ARG(msgId));
+        _lastMsg[buffer] = msgId;
+        emit lastMsgSet(buffer, msgId);
+    }
+
     virtual inline void requestSetLastSeenMsg(BufferId buffer, const MsgId& msgId) { REQUEST(ARG(buffer), ARG(msgId)) }
     virtual inline void requestSetMarkerLine(BufferId buffer, const MsgId& msgId)
     {
     virtual inline void requestSetLastSeenMsg(BufferId buffer, const MsgId& msgId) { REQUEST(ARG(buffer), ARG(msgId)) }
     virtual inline void requestSetMarkerLine(BufferId buffer, const MsgId& msgId)
     {
@@ -110,6 +122,7 @@ public slots:
     virtual inline void markBufferAsRead(BufferId buffer) { SYNC(ARG(buffer)) emit bufferMarkedAsRead(buffer); }
 
 signals:
     virtual inline void markBufferAsRead(BufferId buffer) { SYNC(ARG(buffer)) emit bufferMarkedAsRead(buffer); }
 
 signals:
+    void lastMsgSet(BufferId buffer, const MsgId& msgId);
     void lastSeenMsgSet(BufferId buffer, const MsgId& msgId);
     void markerLineSet(BufferId buffer, const MsgId& msgId);
     void bufferRemoved(BufferId buffer);
     void lastSeenMsgSet(BufferId buffer, const MsgId& msgId);
     void markerLineSet(BufferId buffer, const MsgId& msgId);
     void bufferRemoved(BufferId buffer);
@@ -124,11 +137,13 @@ protected slots:
     bool setMarkerLine(BufferId buffer, const MsgId& msgId);
 
 protected:
     bool setMarkerLine(BufferId buffer, const MsgId& msgId);
 
 protected:
+    inline QList<BufferId> lastBufferIds() const { return _lastMsg.keys(); }
     inline QList<BufferId> lastSeenBufferIds() const { return _lastSeenMsg.keys(); }
     inline QList<BufferId> markerLineBufferIds() const { return _markerLines.keys(); }
     inline QHash<BufferId, MsgId> markerLines() const { return _markerLines; }
 
 private:
     inline QList<BufferId> lastSeenBufferIds() const { return _lastSeenMsg.keys(); }
     inline QList<BufferId> markerLineBufferIds() const { return _markerLines.keys(); }
     inline QHash<BufferId, MsgId> markerLines() const { return _markerLines; }
 
 private:
+    QHash<BufferId, MsgId> _lastMsg;
     QHash<BufferId, MsgId> _lastSeenMsg;
     QHash<BufferId, MsgId> _markerLines;
     QHash<BufferId, Message::Types> _bufferActivities;
     QHash<BufferId, MsgId> _lastSeenMsg;
     QHash<BufferId, MsgId> _markerLines;
     QHash<BufferId, Message::Types> _bufferActivities;
diff --git a/src/core/SQL/PostgreSQL/select_buffer_last_messages.sql b/src/core/SQL/PostgreSQL/select_buffer_last_messages.sql
new file mode 100644 (file)
index 0000000..784635a
--- /dev/null
@@ -0,0 +1,3 @@
+SELECT bufferid, lastmsgid
+FROM buffer
+WHERE userid = :userid
diff --git a/src/core/SQL/SQLite/select_buffer_last_messages.sql b/src/core/SQL/SQLite/select_buffer_last_messages.sql
new file mode 100644 (file)
index 0000000..784635a
--- /dev/null
@@ -0,0 +1,3 @@
+SELECT bufferid, lastmsgid
+FROM buffer
+WHERE userid = :userid
index ce8693a..d2b8092 100644 (file)
@@ -536,6 +536,14 @@ public:
      */
     QString strictSysIdent(UserId user) const;
 
      */
     QString strictSysIdent(UserId user) const;
 
+    //! Get a Hash of all last message ids
+    /** This Method is called when the Quassel Core is started to restore the lastMsgIds
+     *  \note This method is threadsafe.
+     *
+     * \param user      The Owner of the buffers
+     */
+    static inline QHash<BufferId, MsgId> bufferLastMsgIds(UserId user) { return instance()->_storage->bufferLastMsgIds(user); }
+
     //! Get a Hash of all last seen message ids
     /** This Method is called when the Quassel Core is started to restore the lastSeenMsgIds
      *  \note This method is threadsafe.
     //! Get a Hash of all last seen message ids
     /** This Method is called when the Quassel Core is started to restore the lastSeenMsgIds
      *  \note This method is threadsafe.
index 8fdb391..2829f5d 100644 (file)
@@ -39,7 +39,8 @@ public:
 };
 
 CoreBufferSyncer::CoreBufferSyncer(CoreSession* parent)
 };
 
 CoreBufferSyncer::CoreBufferSyncer(CoreSession* parent)
-    : BufferSyncer(Core::bufferLastSeenMsgIds(parent->user()),
+    : BufferSyncer(Core::bufferLastMsgIds(parent->user()),
+                   Core::bufferLastSeenMsgIds(parent->user()),
                    Core::bufferMarkerLineMsgIds(parent->user()),
                    Core::bufferActivities(parent->user()),
                    Core::highlightCounts(parent->user()),
                    Core::bufferMarkerLineMsgIds(parent->user()),
                    Core::bufferActivities(parent->user()),
                    Core::highlightCounts(parent->user()),
index 9374a48..90b0fdb 100644 (file)
@@ -1385,6 +1385,34 @@ bool PostgreSqlStorage::mergeBuffersPermanently(const UserId& user, const Buffer
     return true;
 }
 
     return true;
 }
 
+QHash<BufferId, MsgId> PostgreSqlStorage::bufferLastMsgIds(UserId user)
+{
+    QHash<BufferId, MsgId> lastMsgHash;
+
+    QSqlDatabase db = logDb();
+    if (!beginReadOnlyTransaction(db)) {
+        qWarning() << "PostgreSqlStorage::bufferLastMsgIds(): cannot start read only transaction!";
+        qWarning() << " -" << qPrintable(db.lastError().text());
+        return lastMsgHash;
+    }
+
+    QSqlQuery query(db);
+    query.prepare(queryString("select_buffer_last_messages"));
+    query.bindValue(":userid", user.toInt());
+    safeExec(query);
+    if (!watchQuery(query)) {
+        db.rollback();
+        return lastMsgHash;
+    }
+
+    while (query.next()) {
+        lastMsgHash[query.value(0).toInt()] = query.value(1).toLongLong();
+    }
+
+    db.commit();
+    return lastMsgHash;
+}
+
 void PostgreSqlStorage::setBufferLastSeenMsg(UserId user, const BufferId& bufferId, const MsgId& msgId)
 {
     QSqlQuery query(logDb());
 void PostgreSqlStorage::setBufferLastSeenMsg(UserId user, const BufferId& bufferId, const MsgId& msgId)
 {
     QSqlQuery query(logDb());
index 86fa204..78ddc9d 100644 (file)
@@ -92,6 +92,7 @@ public slots:
     bool removeBuffer(const UserId& user, const BufferId& bufferId) override;
     bool renameBuffer(const UserId& user, const BufferId& bufferId, const QString& newName) override;
     bool mergeBuffersPermanently(const UserId& user, const BufferId& bufferId1, const BufferId& bufferId2) override;
     bool removeBuffer(const UserId& user, const BufferId& bufferId) override;
     bool renameBuffer(const UserId& user, const BufferId& bufferId, const QString& newName) override;
     bool mergeBuffersPermanently(const UserId& user, const BufferId& bufferId1, const BufferId& bufferId2) override;
+    QHash<BufferId, MsgId> bufferLastMsgIds(UserId user) override;
     void setBufferLastSeenMsg(UserId user, const BufferId& bufferId, const MsgId& msgId) override;
     QHash<BufferId, MsgId> bufferLastSeenMsgIds(UserId user) override;
     void setBufferMarkerLineMsg(UserId user, const BufferId& bufferId, const MsgId& msgId) override;
     void setBufferLastSeenMsg(UserId user, const BufferId& bufferId, const MsgId& msgId) override;
     QHash<BufferId, MsgId> bufferLastSeenMsgIds(UserId user) override;
     void setBufferMarkerLineMsg(UserId user, const BufferId& bufferId, const MsgId& msgId) override;
index 026b4dc..dc5b546 100644 (file)
@@ -1485,6 +1485,34 @@ bool SqliteStorage::mergeBuffersPermanently(const UserId& user, const BufferId&
     return !error;
 }
 
     return !error;
 }
 
+QHash<BufferId, MsgId> SqliteStorage::bufferLastMsgIds(UserId user)
+{
+    QHash<BufferId, MsgId> lastMsgHash;
+
+    QSqlDatabase db = logDb();
+    db.transaction();
+
+    bool error = false;
+    {
+        QSqlQuery query(db);
+        query.prepare(queryString("select_buffer_last_messages"));
+        query.bindValue(":userid", user.toInt());
+
+        lockForRead();
+        safeExec(query);
+        error = !watchQuery(query);
+        if (!error) {
+            while (query.next()) {
+                lastMsgHash[query.value(0).toInt()] = query.value(1).toLongLong();
+            }
+        }
+    }
+
+    db.commit();
+    unlock();
+    return lastMsgHash;
+}
+
 void SqliteStorage::setBufferLastSeenMsg(UserId user, const BufferId& bufferId, const MsgId& msgId)
 {
     QSqlDatabase db = logDb();
 void SqliteStorage::setBufferLastSeenMsg(UserId user, const BufferId& bufferId, const MsgId& msgId)
 {
     QSqlDatabase db = logDb();
index 7c579b0..3e9de41 100644 (file)
@@ -96,6 +96,7 @@ public slots:
     bool removeBuffer(const UserId& user, const BufferId& bufferId) override;
     bool renameBuffer(const UserId& user, const BufferId& bufferId, const QString& newName) override;
     bool mergeBuffersPermanently(const UserId& user, const BufferId& bufferId1, const BufferId& bufferId2) override;
     bool removeBuffer(const UserId& user, const BufferId& bufferId) override;
     bool renameBuffer(const UserId& user, const BufferId& bufferId, const QString& newName) override;
     bool mergeBuffersPermanently(const UserId& user, const BufferId& bufferId1, const BufferId& bufferId2) override;
+    QHash<BufferId, MsgId> bufferLastMsgIds(UserId user) override;
     void setBufferLastSeenMsg(UserId user, const BufferId& bufferId, const MsgId& msgId) override;
     QHash<BufferId, MsgId> bufferLastSeenMsgIds(UserId user) override;
     void setBufferMarkerLineMsg(UserId user, const BufferId& bufferId, const MsgId& msgId) override;
     void setBufferLastSeenMsg(UserId user, const BufferId& bufferId, const MsgId& msgId) override;
     QHash<BufferId, MsgId> bufferLastSeenMsgIds(UserId user) override;
     void setBufferMarkerLineMsg(UserId user, const BufferId& bufferId, const MsgId& msgId) override;
index b49aee0..5d47c09 100644 (file)
@@ -386,6 +386,12 @@ public slots:
      */
     virtual void setBufferLastSeenMsg(UserId user, const BufferId& bufferId, const MsgId& msgId) = 0;
 
      */
     virtual void setBufferLastSeenMsg(UserId user, const BufferId& bufferId, const MsgId& msgId) = 0;
 
+    //! Get a Hash of all last message ids
+    /** This Method is called when the Quassel Core is started to restore the lastMsgIds
+     * \param user      The Owner of the buffers
+     */
+    virtual QHash<BufferId, MsgId> bufferLastMsgIds(UserId user) = 0;
+
     //! Get a Hash of all last seen message ids
     /** This Method is called when the Quassel Core is started to restore the lastSeenMsgIds
      * \param user      The Owner of the buffers
     //! Get a Hash of all last seen message ids
     /** This Method is called when the Quassel Core is started to restore the lastSeenMsgIds
      * \param user      The Owner of the buffers