Testing the new SyncObjects concept - looking good so far
[quassel.git] / src / client / clientbacklogmanager.cpp
index b485726..f579e60 100644 (file)
@@ -1,5 +1,5 @@
 /***************************************************************************
- *   Copyright (C) 2005-08 by the Quassel IRC Team                         *
+ *   Copyright (C) 2005-09 by the Quassel Project                          *
  *   devel@quassel-irc.org                                                 *
  *                                                                         *
  *   This program is free software; you can redistribute it and/or modify  *
 #include "clientbacklogmanager.h"
 
 #include "abstractmessageprocessor.h"
+#include "backlogsettings.h"
 #include "backlogrequester.h"
 #include "client.h"
 
-#include <QDebug>
 #include <ctime>
 
+#include <QDebug>
+
+INIT_SYNCABLE_OBJECT(ClientBacklogManager)
 ClientBacklogManager::ClientBacklogManager(QObject *parent)
   : BacklogManager(parent),
-    _buffer(true)
+    _requester(0)
 {
 }
 
-void ClientBacklogManager::receiveBacklog(BufferId bufferId, int lastMsgs, int offset, QVariantList msgs) {
-  Q_UNUSED(lastMsgs)
-  Q_UNUSED(offset)
+QVariantList ClientBacklogManager::requestBacklog(BufferId bufferId, MsgId first, MsgId last, int limit, int additional) {
+  _buffersRequested << bufferId;
+  return BacklogManager::requestBacklog(bufferId, first, last, limit, additional);
+}
 
-  if(msgs.isEmpty())
-    return;
+void ClientBacklogManager::receiveBacklog(BufferId bufferId, MsgId first, MsgId last, int limit, int additional, QVariantList msgs) {
+  Q_UNUSED(first) Q_UNUSED(last) Q_UNUSED(limit) Q_UNUSED(additional)
 
-  //QTime start = QTime::currentTime();
-  QList<Message> msglist;
+  emit messagesReceived(bufferId, msgs.count());
+
+  MessageList msglist;
   foreach(QVariant v, msgs) {
     Message msg = v.value<Message>();
     msg.setFlags(msg.flags() | Message::Backlog);
     msglist << msg;
   }
 
-  if(_buffer) {
-    _messageBuffer << msglist;
-    _buffersWaiting.remove(bufferId);
-    if(_buffersWaiting.isEmpty()) {
-      _buffer = false;
-      clock_t start_t = clock();
-      qSort(_messageBuffer);
-      Client::messageProcessor()->process(_messageBuffer);
-      clock_t end_t = clock();
-      qDebug() << "Processed" << _messageBuffer.count() << "Messages in" << (float)(end_t - start_t) / CLOCKS_PER_SEC << "seconds ==" << end_t - start_t << "clocks.";
-      _messageBuffer.clear();
+  if(isBuffering()) {
+    bool lastPart = !_requester->buffer(bufferId, msglist);
+    updateProgress(_requester->totalBuffers() - _requester->buffersWaiting(), _requester->totalBuffers());
+    if(lastPart) {
+      dispatchMessages(_requester->bufferedMessages(), true);
+      _requester->flushBuffer();
     }
   } else {
-    Client::messageProcessor()->process(msglist);
+    dispatchMessages(msglist);
   }
-  //qDebug() << "processed" << msgs.count() << "backlog lines in" << start.msecsTo(QTime::currentTime());
 }
 
-QVariantList ClientBacklogManager::requestBacklog(BufferId bufferId, int lastMsgs, int offset) {
-  if(_buffer)
-    _buffersWaiting << bufferId;
+void ClientBacklogManager::receiveBacklogAll(MsgId first, MsgId last, int limit, int additional, QVariantList msgs) {
+  Q_UNUSED(first) Q_UNUSED(last) Q_UNUSED(limit) Q_UNUSED(additional)
 
-  return BacklogManager::requestBacklog(bufferId, lastMsgs, offset);
+  MessageList msglist;
+  foreach(QVariant v, msgs) {
+    Message msg = v.value<Message>();
+    msg.setFlags(msg.flags() | Message::Backlog);
+    msglist << msg;
+  }
+
+  dispatchMessages(msglist);
 }
 
 void ClientBacklogManager::requestInitialBacklog() {
-  FixedBacklogRequester backlogRequester(this);
-  backlogRequester.requestBacklog();
+  if(_requester && !_buffersRequested.isEmpty()) {
+    qWarning() << "ClientBacklogManager::requestInitialBacklog() called twice in the same session! (Backlog has already been requested)";
+    return;
+  }
+
+  BacklogSettings settings;
+  switch(settings.requesterType()) {
+  case BacklogRequester::GlobalUnread:
+    _requester = new GlobalUnreadBacklogRequester(this);
+    break;
+  case BacklogRequester::PerBufferUnread:
+    _requester = new PerBufferUnreadBacklogRequester(this);
+    break;
+  case BacklogRequester::PerBufferFixed:
+  default:
+    _requester = new FixedBacklogRequester(this);
+  };
+
+  _requester->requestInitialBacklog();
+  if(_requester->isBuffering()) {
+    updateProgress(0, _requester->totalBuffers());
+  }
+}
+
+BufferIdList ClientBacklogManager::filterNewBufferIds(const BufferIdList &bufferIds) {
+  BufferIdList newBuffers;
+  QSet<BufferId> availableBuffers = Client::networkModel()->allBufferIds().toSet();
+  foreach(BufferId bufferId, bufferIds) {
+    if(_buffersRequested.contains(bufferId) || !availableBuffers.contains(bufferId))
+      continue;
+    newBuffers << bufferId;
+  }
+  return newBuffers;
+}
+
+void ClientBacklogManager::checkForBacklog(const QList<BufferId> &bufferIds) {
+  if(!_requester) {
+    // during client start up this message is to be expected in some situations.
+    qDebug() << "ClientBacklogManager::checkForBacklog(): no active backlog requester (yet?).";
+    return;
+  }
+  switch(_requester->type()) {
+  case BacklogRequester::GlobalUnread:
+    break;
+  case BacklogRequester::PerBufferUnread:
+  case BacklogRequester::PerBufferFixed:
+  default:
+    {
+      BufferIdList buffers = filterNewBufferIds(bufferIds);
+      if(!buffers.isEmpty())
+        _requester->requestBacklog(buffers);
+    }
+  };
+}
+
+bool ClientBacklogManager::isBuffering() {
+  return _requester && _requester->isBuffering();
+}
+
+void ClientBacklogManager::dispatchMessages(const MessageList &messages, bool sort) {
+  if(messages.isEmpty())
+    return;
+
+  MessageList msgs = messages;
+
+  clock_t start_t = clock();
+  if(sort)
+    qSort(msgs);
+  Client::messageProcessor()->process(msgs);
+  clock_t end_t = clock();
+
+  emit messagesProcessed(tr("Processed %1 messages in %2 seconds.").arg(messages.count()).arg((float)(end_t - start_t) / CLOCKS_PER_SEC));
 }
 
 void ClientBacklogManager::reset() {
-  _buffer = true;
-  _messageBuffer.clear();
-  _buffersWaiting.clear();
+  delete _requester;
+  _requester = 0;
+  _buffersRequested.clear();
 }