~ubuntu-branches/ubuntu/trusty/kvirc/trusty-proposed

« back to all changes in this revision

Viewing changes to src/kvirc/kernel/kvi_lagmeter.cpp

  • Committer: Bazaar Package Importer
  • Author(s): Kai Wasserbäch, Kai Wasserbäch, Raúl Sánchez Siles
  • Date: 2011-02-12 10:40:21 UTC
  • mfrom: (14.1.3 sid)
  • Revision ID: james.westby@ubuntu.com-20110212104021-5mh4f75jlku20mnt
The combined "Twisted Experiment" and "Nocturnal Raid" release.

[ Kai Wasserbäch ]
* Synced to upstream's SVN revision 5467.
* debian/rules:
  - Added .PHONY line.
  - Resurrect -DMANUAL_REVISION, got lost somewhere and we build SVN
    revisions again.
  - Replace "-DWITH_NO_EMBEDDED_CODE=YES" with "-DWANT_CRYPTOPP=YES".
  - Change the remaining -DWITH/-DWITHOUT to the new -DWANT syntax.
* debian/control:
  - Removed DMUA, I'm a DD now.
  - Changed my e-mail address.
  - Removed unneeded relationships (no upgrades over two releases are
    supported).
  - Fix Suggests for kvirc-dbg.
  - kvirc-data: Make the "Suggests: kvirc" a Recommends, doesn't make much
    sense to install the -data package without the program.
* debian/source/local-options: Added with "unapply-patches".
* debian/kvirc.lintian-overrides: Updated to work for 4.1.1.
* debian/patches/21_make_shared-mime-info_B-D_superfluous.patch: Updated.
* debian/kvirc-data.install: Added .notifyrc.

[ Raúl Sánchez Siles ]
* Stating the right version where kvirc-data break and replace should happen.
* Fixing link to license file.
* Added French and Portuguese man pages.

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
//=============================================================================
2
 
//
3
 
//   File : kvi_lagmeter.cpp
4
 
//   Creation date : Fri Oct 18 13:31:36 CEST 1999 by Juanjo �lvarez
5
 
//
6
 
//   This file is part of the KVirc irc client distribution
7
 
//   Copyright (C) 1999 Juanjo �lvarez
8
 
//   Copyright (C) 2000-2008 Szymon Stefanek (pragma at kvirc dot net)
9
 
//
10
 
//   This program is FREE software. You can redistribute it and/or
11
 
//   modify it under the terms of the GNU General Public License
12
 
//   as published by the Free Software Foundation; either version 2
13
 
//   of the License, or (at your opinion) any later version.
14
 
//
15
 
//   This program is distributed in the HOPE that it will be USEFUL,
16
 
//   but WITHOUT ANY WARRANTY; without even the implied warranty of
17
 
//   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
18
 
//   See the GNU General Public License for more details.
19
 
//
20
 
//   You should have received a copy of the GNU General Public License
21
 
//   along with this program. If not, write to the Free Software Foundation,
22
 
//   Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
23
 
//
24
 
//=============================================================================
25
 
 
26
 
 
27
 
 
28
 
#include "kvi_lagmeter.h"
29
 
#include "kvi_options.h"
30
 
#include "kvi_kvs_eventtriggers.h"
31
 
#include "kvi_parameterlist.h"
32
 
#include "kvi_ircconnection.h"
33
 
#include "kvi_irccontext.h"
34
 
#include "kvi_frame.h"
35
 
#include "kvi_console.h"
36
 
#include "kvi_time.h"
37
 
#include "kvi_ircconnectionuserinfo.h"
38
 
#include "kvi_ircconnectionserverinfo.h"
39
 
#include "kvi_out.h"
40
 
#include "kvi_locale.h"
41
 
 
42
 
KviLagMeter::KviLagMeter(KviIrcConnection * c)
43
 
: QObject()
44
 
{
45
 
        m_pConnection = c;
46
 
        m_pCheckList = new KviPointerList<KviLagCheck>;
47
 
        m_pCheckList->setAutoDelete(true);
48
 
        m_uLag = 0;
49
 
        m_uLastEmittedLag = 0;
50
 
        m_uLastReliability = 0;
51
 
        m_tLastCompleted = 0;
52
 
        m_tLastOwnCheck = 0;
53
 
        m_tFirstOwnCheck = 0;
54
 
        m_bOnAlarm = false;
55
 
        m_pDeletionSignal = 0;
56
 
        
57
 
        // FIXME: We could use the KviIrcConnection::heartbeat() here!
58
 
        if(KVI_OPTION_UINT(KviOption_uintLagMeterHeartbeat) < 2000)
59
 
                KVI_OPTION_UINT(KviOption_uintLagMeterHeartbeat) = 2000; // kinda absurd
60
 
 
61
 
        if(KVI_OPTION_UINT(KviOption_uintLagMeterHeartbeat) > 10000)
62
 
                KVI_OPTION_UINT(KviOption_uintLagMeterHeartbeat) = 10000; // kinda absurd
63
 
        
64
 
        startTimer(KVI_OPTION_UINT(KviOption_uintLagMeterHeartbeat)); // 5 seconds by default
65
 
}
66
 
 
67
 
KviLagMeter::~KviLagMeter()
68
 
{
69
 
        if(m_pDeletionSignal)*m_pDeletionSignal = true;
70
 
        delete m_pCheckList;
71
 
}
72
 
 
73
 
unsigned int KviLagMeter::secondsSinceLastCompleted()
74
 
{
75
 
        struct timeval tv;
76
 
        kvi_gettimeofday(&tv,0);
77
 
        return tv.tv_sec - m_tLastCompleted;
78
 
}
79
 
 
80
 
void KviLagMeter::timerEvent(QTimerEvent *)
81
 
{
82
 
        if(m_pConnection->state() != KviIrcConnection::Connected)return; // do nothing atm
83
 
 
84
 
        // If the lag has changed emit our signals
85
 
        if((m_uLag / 10) != (m_uLastEmittedLag / 10))
86
 
        {
87
 
                m_uLastEmittedLag = m_uLag;
88
 
                g_pFrame->childConnectionLagChange(m_pConnection);
89
 
 
90
 
                KviStr szLag(KviStr::Format,"%u",m_uLag);
91
 
                
92
 
                bool bDeletionSignal = false;
93
 
                m_pDeletionSignal = &bDeletionSignal;
94
 
 
95
 
                if((!m_bOnAlarm) && (m_uLag > KVI_OPTION_UINT(KviOption_uintLagAlarmTime)))
96
 
                {
97
 
                        KVS_TRIGGER_EVENT_2_HALTED(KviEvent_OnLagAlarmTimeUp,
98
 
                                m_pConnection->console(),m_pConnection->serverInfo()->name(),QString(szLag.ptr()));
99
 
                        if(bDeletionSignal)return; // killed , probably by a quit -f -u
100
 
                        m_bOnAlarm = true;
101
 
                } else if(m_bOnAlarm) 
102
 
                {
103
 
                        KVS_TRIGGER_EVENT_2_HALTED(KviEvent_OnLagAlarmTimeDown,
104
 
                                m_pConnection->console(),m_pConnection->serverInfo()->name(),QString(szLag.ptr()));
105
 
                        if(bDeletionSignal)return; // killed , probably by a quit -f -u
106
 
                        m_bOnAlarm = false;
107
 
                }
108
 
 
109
 
                KVS_TRIGGER_EVENT_2_HALTED(KviEvent_OnLagCheck,
110
 
                        m_pConnection->console(),m_pConnection->serverInfo()->name(),QString(szLag.ptr()));
111
 
                if(bDeletionSignal)return; // killed , probably by a quit -f -u
112
 
 
113
 
                m_pDeletionSignal = 0;
114
 
        }
115
 
 
116
 
        // get current time
117
 
        struct timeval tv;
118
 
        kvi_gettimeofday(&tv,0);
119
 
        unsigned int uDiff = tv.tv_sec - m_tLastCompleted;
120
 
        unsigned int uHeartbeat = KVI_OPTION_UINT(KviOption_uintLagMeterHeartbeat) / 1000;
121
 
        if(uHeartbeat < 2)uHeartbeat = 2;
122
 
        // we keep the last lag value for an amount of time
123
 
        // depending on its reliability.
124
 
        // Since reliability ranges from 10 to 100 we keep the lags
125
 
        // for (hrtbt * 4) + (reliability / 2) seconds (which means from 25 to 70 seconds by default)
126
 
        if(uDiff <= ((uHeartbeat * 4) + (m_uLastReliability / 2)))return; // nothing to do, the actual value is accurate
127
 
 
128
 
        // the last completed check has been completed a lot of time ago
129
 
        // do we have some checks on the queue ?
130
 
        if(m_pCheckList->count() > 0)
131
 
        {
132
 
                // if the first registered check is not too outdated
133
 
                // we wait a little more for it to return
134
 
                KviLagCheck * c = m_pCheckList->first();
135
 
                if(c)
136
 
                {
137
 
                        if((tv.tv_sec - c->lSecs) <= 10)return;
138
 
                }
139
 
                // the first check was registered more than 10 secs before
140
 
                if(m_tLastOwnCheck > 0)
141
 
                {
142
 
                        // hm.. we have already sent our own (reliable) check after the last completed
143
 
                        // make the lag grow (we're pretty sure it's growing)
144
 
                        uDiff = (tv.tv_sec - m_tFirstOwnCheck) * 1000;
145
 
                        if(m_uLag < uDiff)m_uLag = uDiff; // the lag grows for sure
146
 
                        uDiff = tv.tv_sec - m_tLastOwnCheck;
147
 
                        if(uDiff < (uHeartbeat * 4))return; // wait a bit...send own checks only every 20 secs (by default) at this point
148
 
                }
149
 
        }
150
 
        // or we have no checks in the queue at all
151
 
        // or it's really time to do something...
152
 
        if(m_tFirstOwnCheck == 0)
153
 
        {
154
 
                if(_OUTPUT_PARANOIC)
155
 
                        m_pConnection->console()->output(KVI_OUT_VERBOSE,__tr2qs("Sending out PING based lag probe"));
156
 
 
157
 
                // this is the first our own lag check since the last succesfull one: use the ping
158
 
                lagCheckRegister("@ping@",70); // the ping may be fooled easily
159
 
                m_pConnection->sendFmtData("PING %s %s",
160
 
                        m_pConnection->encodeText( m_pConnection->userInfo()->nickName() ).data(),
161
 
                        m_pConnection->encodeText( m_pConnection->serverInfo()->name() ).data() );
162
 
                m_tFirstOwnCheck = tv.tv_sec;
163
 
        } else {
164
 
                if(_OUTPUT_PARANOIC)
165
 
                        m_pConnection->console()->output(KVI_OUT_VERBOSE,__tr2qs("Sending out CTCP based lag probe"));
166
 
 
167
 
                // we have already sent a ping but we got no reply
168
 
                // try with another method... even if this will reset our idle time
169
 
                KviStr tmp(KviStr::Format,"%d%d-yeah-:)",tv.tv_sec,tv.tv_usec);
170
 
                lagCheckRegister(tmp.ptr(),100); // almost impossible to fool
171
 
                m_pConnection->sendFmtData("NOTICE %s :%cLAGCHECK %s%c",
172
 
                        m_pConnection->encodeText( m_pConnection->userInfo()->nickName() ).data(),
173
 
                        0x01,
174
 
                        tmp.ptr(),
175
 
                        0x01);
176
 
        }
177
 
        m_tLastOwnCheck = tv.tv_sec;
178
 
}
179
 
 
180
 
void KviLagMeter::lagCheckRegister(const char * key,unsigned int uReliability)
181
 
{
182
 
        if(uReliability < 10)return; // what the heck of a lag check is this ?
183
 
        // store the lagcheck structure and just return
184
 
 
185
 
        if(_OUTPUT_PARANOIC)
186
 
                m_pConnection->console()->output(KVI_OUT_VERBOSE,__tr2qs("Registered lag check with reliability %u (%s)"),uReliability,key);
187
 
 
188
 
        KviLagCheck * c = new KviLagCheck;
189
 
        c->szKey = key;
190
 
        struct timeval tv;
191
 
        kvi_gettimeofday(&tv,0);
192
 
        c->lSecs = tv.tv_sec;
193
 
        c->lUSecs = tv.tv_usec;
194
 
        c->uReliability = uReliability <= 100 ? uReliability : 100;
195
 
        m_pCheckList->append(c);
196
 
        while(m_pCheckList->count() > 30)
197
 
        {
198
 
                // we're fried :/
199
 
                // either our ping mechanism is not working
200
 
                // or the server is stoned...
201
 
                m_pCheckList->removeFirst();
202
 
        }
203
 
}
204
 
 
205
 
bool KviLagMeter::lagCheckComplete(const char * key)
206
 
{
207
 
        // find this lag check
208
 
        KviLagCheck * c;
209
 
        for(c = m_pCheckList->first();c;c = m_pCheckList->next())
210
 
        {
211
 
                if(kvi_strEqualCS(c->szKey.ptr(),key))break;
212
 
        }
213
 
        if(!c)return false; // not found
214
 
        // kill any earlier lag checks (IRC is a sequential proto)
215
 
        while(m_pCheckList->first() != c)m_pCheckList->removeFirst();
216
 
 
217
 
        if(_OUTPUT_PARANOIC)
218
 
                m_pConnection->console()->output(KVI_OUT_VERBOSE,__tr2qs("Lag check completed (%s)"),key);
219
 
 
220
 
        struct timeval tv;
221
 
        kvi_gettimeofday(&tv,0);
222
 
 
223
 
        unsigned int uLag = ((tv.tv_sec - c->lSecs) * 1000);
224
 
        if(tv.tv_usec < c->lUSecs)uLag -= ((c->lUSecs - tv.tv_usec) / 1000);
225
 
        else uLag += ((tv.tv_usec - c->lUSecs) / 1000);
226
 
        
227
 
        // now check the reliability
228
 
 
229
 
        if(m_uLastReliability > c->uReliability)
230
 
        {
231
 
                // the actual data is more reliable than the new one :/
232
 
                // change the real lag only by a certain amount
233
 
                // c->uRel : 100 = uLag : m_uLag
234
 
                m_uLag = ((uLag * c->uReliability) + (m_uLag * m_uLastReliability)) / (c->uReliability + m_uLastReliability);
235
 
        } else {
236
 
                // the actual data is less reliable than the new one
237
 
                m_uLag = uLag;
238
 
        }
239
 
 
240
 
        m_tLastCompleted = tv.tv_sec; // now
241
 
        m_tLastOwnCheck = 0;
242
 
        m_tFirstOwnCheck = 0;
243
 
        m_uLastReliability = c->uReliability;
244
 
 
245
 
        m_pCheckList->removeFirst();
246
 
        
247
 
        return true;
248
 
}
249
 
 
250
 
void KviLagMeter::lagCheckAbort(const char * key)
251
 
{
252
 
        KviPointerList<KviLagCheck> l;
253
 
        l.setAutoDelete(false);
254
 
        KviLagCheck * c;
255
 
 
256
 
        if(_OUTPUT_PARANOIC)
257
 
                m_pConnection->console()->output(KVI_OUT_VERBOSE,__tr2qs("Lag check aborted (%s)"),key);
258
 
 
259
 
        for(c = m_pCheckList->first();c;c = m_pCheckList->next())
260
 
                if(kvi_strEqualCS(c->szKey.ptr(),key))l.append(c);
261
 
        for(c = l.first();c;c = l.next())m_pCheckList->removeRef(c);
262
 
}
263
 
 
264
 
#ifndef COMPILE_USE_STANDALONE_MOC_SOURCES
265
 
#include "kvi_lagmeter.moc"
266
 
#endif //!COMPILE_USE_STANDALONE_MOC_SOURCES