diff --git a/src/irc/ircqueue.cpp b/src/irc/ircqueue.cpp index 11016231..3cc33a5a 100644 --- a/src/irc/ircqueue.cpp +++ b/src/irc/ircqueue.cpp @@ -1,202 +1,210 @@ /* This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License or (at your option) version 3 or any later version accepted by the membership of KDE e.V. (or its successor approved by the membership of KDE e.V.), which shall act as a proxy defined in Section 14 of version 3 of the license. */ /* Copyright (C) 2008 Eli J. MacKenzie */ #include "ircqueue.h" #include #include #include "server.h" +IRCMessage::IRCMessage(const QString &str) + : s(str) //, codec(QTextCodec::codecForName("utf8")) +{ + t.start(); +} + +//// + int IRCQueue::EmptyingRate::nextInterval(int, int elapsed) { if (!isValid()) return 0; //KX << _S(m_interval) << endl; if (m_type == Lines) { int i = m_interval/m_rate; //KX << _S(i) << endl; if (isetSingleShot(true); connect(m_timer, &QTimer::timeout, this, &IRCQueue::sendNow); if (server) { connect(server, SIGNAL(serverOnline(bool)), SLOT(serverOnline(bool))); connect(server, SIGNAL(sentStat(int,int,IRCQueue*)), SLOT(sent(int,int,IRCQueue*))); m_blocked=!(m_server->isConnected()); } } IRCQueue::~IRCQueue() { qDebug(); } QString IRCQueue::pop() { if (m_pending.isEmpty()) return QString(); IRCMessage msg=m_pending.first(); m_pending.pop_front(); m_lastWait=msg.age(); m_lastSent=QTime::currentTime(); return msg.text(); } int IRCQueue::nextSize() { if (m_pending.isEmpty()) return 0; return m_pending.first().text().length(); } int IRCQueue::currentWait() { if (m_pending.isEmpty()) return 0; return m_pending.first().age(); } int IRCQueue::elapsed() { if (m_startedAt.isNull()) return 0; else return m_startedAt.elapsed(); //FIXME if its been more than a day since this queue was used, this breaks } int IRCQueue::linesSent() const { return m_linesSent; } int IRCQueue::bytesSent() const { return m_bytesSent; } ///Feedback indicating size of data sent to update statistics. Not necessarily data from this queue!!! void IRCQueue::sent(int, int e, IRCQueue *wq) { //KX << Q_FUNC_INFO << _S(m_mine) << endl; m_globalLinesSent++; m_globalBytesSent+=e; // we don't care about the unencoded bytes, we want what went to the server if (wq == this) { m_linesSent++; m_bytesSent+=e; } } void IRCQueue::enqueue(const QString& line) { m_pending.append(IRCMessage(line)); if (!m_timer->isActive()) adjustTimer(); } //starts timer if stopped, adjusts interval if necessary void IRCQueue::adjustTimer() { int msec; msec=getRate().nextInterval(nextSize(), elapsed()); //if (m_myIndex == 0) // KX << _S(msec) << endl; m_timer->start(msec); m_startedAt.start(); return; } bool IRCQueue::doSend() { bool p=!m_pending.isEmpty(); if (p) { QString s=pop(); if (s.isEmpty()) return doSend(); //can't send empty strings, but no point in losing the timeslot m_server->toServer(s, this); m_startedAt.start(); } return p;//if we sent something, fire the timer again } ///it would probably be better to delete and recreate the queue. void IRCQueue::reset() { // KX << Q_FUNC_INFO << endl; m_timer->stop(); m_lastWait=0; if (m_server) m_blocked=!(m_server->isConnected()); //FIXME (maybe) "we can't do this anymore because blocked can't correspond to whether the server is online, instead must correspond to whether the socket has become writable (readyWrite)" m_startedAt=m_globalLastSent=m_lastSent=QTime(); m_pending.clear(); m_linesSent=m_bytesSent=m_globalBytesSent=m_globalLinesSent=0; } //called when the timer fires. void IRCQueue::sendNow() { if (doSend()) adjustTimer(); //else //its a single-shot timer so if we don't adjust it, it won't run :) } ///lets us know we should block output void IRCQueue::serverOnline(bool on) { if (m_blocked!=on) return; m_blocked=!on; if (m_blocked && m_timer->isActive()) reset(); else if (!m_blocked && !m_timer->isActive() && nextSize()) { adjustTimer(); } } diff --git a/src/irc/ircqueue.h b/src/irc/ircqueue.h index 3f7f0c80..7a917768 100644 --- a/src/irc/ircqueue.h +++ b/src/irc/ircqueue.h @@ -1,147 +1,143 @@ /* This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License or (at your option) version 3 or any later version accepted by the membership of KDE e.V. (or its successor approved by the membership of KDE e.V.), which shall act as a proxy defined in Section 14 of version 3 of the license. */ /* Copyright (C) 2008 Eli J. MacKenzie */ #ifndef IRCQUEUE_H #define IRCQUEUE_H #include #include #include +#include class QTimer; class Server; //channel.cpp, outputfilter.cpp, query.cpp, server.cpp, statuspanel.cpp /** * A message from or to an IRC server. * * Contains all we know about the message, which currently consists of the text, the time it was created, * and its original encoding. (Since currently these objects are only used internally, we know the message * is Unicode.) */ struct IRCMessage { - IRCMessage() : t(QTime::currentTime()) //, codec(QTextCodec::codecForName("utf8")) - {} ///< this constructor required for QValueList, do not use - /** Make a new IRCMessage with timestamp of QTime::currentTime(). Note the constructor takes a QString, not a const QString& or a QString *. If you want to modify the contained text, put it back with setText. */ - IRCMessage(QString i) : s(i), t(QTime::currentTime()) //, codec(QTextCodec::codecForName("utf8")) - {} + IRCMessage(const QString &str); - QString text() { return s; } - int age() { return t.elapsed(); } - QTime time() { return t; } - void setText(QString text) { s=text; } + QString text() const { return s; } + int age() const { return t.elapsed(); } // in milliseconds + void setText(const QString &text) { s=text; } private: QString s; - QTime t; + QElapsedTimer t; //FIXME wire this up //QTextCodec* codec; - //operator const char * () const { return codec->fromUnicode(text()); } + //operator QByteArray () const { return codec->fromUnicode(text()); } }; /** * Provides a self-sending queue of IRCMessages. * * Messages enqueued in this server can only be erased via reset() or sent to the attached server. * The server and the emptying rates cannot be changed, if you want to do that construct a new queue. */ class IRCQueue: public QObject { Q_OBJECT public: struct EmptyingRate { enum RateType { Lines, ///< Lines per interval. Bytes ///< Bytes per interval. Not implemented. FIXME }; EmptyingRate(int rate=39, int msec_interval=59000, RateType type=Lines): m_rate(rate), m_interval(msec_interval), m_type(type) { } int nextInterval(int byte_size, int msec_since_last); int m_rate; int m_interval; RateType m_type; bool isValid() { return m_rate > 0; } bool operator==(const EmptyingRate& o) const { return (m_rate == o.m_rate && m_interval == o.m_interval && m_type == o.m_type)? true : false; } }; IRCQueue(Server *server, EmptyingRate& rate, int myindex=0); ~IRCQueue() override; void enqueue(const QString& line); void reset(); EmptyingRate& getRate();// { return &m_rate; } bool isValid() { return m_rate.isValid(); } bool isEmpty() { return m_pending.isEmpty(); } //WTF? why are there two of these. //These are decoupled for a reason, what is it? int currentWait(); ///< Time in ms that the front has been waiting int elapsed(); ///< How long has the queue been running since it was last started? int nextSize(); ///< Current size of front int pendingMessages() { return m_pending.count(); } int linesSent() const; ///< count of lines sent by this queue int bytesSent() const; ///< count of bytes sent by this queue ///Time in milliseconds that the previous message waited int lastWait() { return m_lastWait; } public Q_SLOTS: void sent(int bytes, int encodedBytes, IRCQueue *); ///< feedback statistics void sendNow(); ///< dumps a line to the socket void serverOnline(bool on); ///< server tells us that the socket is ready protected: QString pop(); ///< pops front, sets statistics void adjustTimer(); ///< sets the next timer interval bool doSend(); ///< pops front and tells the server to send it. returns true if we sent something EmptyingRate& m_rate; private: QList m_pending; QTimer *m_timer; bool m_blocked; bool m_online; Server *m_server; QTime m_startedAt; QTime m_lastSent, m_globalLastSent; int m_linesSent, m_globalLinesSent; int m_bytesSent, m_globalBytesSent; int m_lastWait; int m_myIndex; }; #endif