From 3b55a62fdcb1f8222de3c2c8fbed530792c419a0 Mon Sep 17 00:00:00 2001 From: Vadim Dashevskiy Date: Fri, 12 Oct 2012 14:53:57 +0000 Subject: GTalkExt, ICQ, IRC, Jabber: folders restructurization git-svn-id: http://svn.miranda-ng.org/main/trunk@1890 1316c22d-e87f-b044-9b9b-93d7a3e3ba9c --- protocols/IcqOscarJ/src/icq_infoupdate.cpp | 401 +++++++++++++++++++++++++++++ 1 file changed, 401 insertions(+) create mode 100644 protocols/IcqOscarJ/src/icq_infoupdate.cpp (limited to 'protocols/IcqOscarJ/src/icq_infoupdate.cpp') diff --git a/protocols/IcqOscarJ/src/icq_infoupdate.cpp b/protocols/IcqOscarJ/src/icq_infoupdate.cpp new file mode 100644 index 0000000000..014df20e01 --- /dev/null +++ b/protocols/IcqOscarJ/src/icq_infoupdate.cpp @@ -0,0 +1,401 @@ +// ---------------------------------------------------------------------------80 +// ICQ plugin for Miranda Instant Messenger +// ________________________________________ +// +// Copyright © 2000-2001 Richard Hughes, Roland Rabien, Tristan Van de Vreede +// Copyright © 2001-2002 Jon Keating, Richard Hughes +// Copyright © 2002-2004 Martin Öberg, Sam Kothari, Robert Rainwater +// Copyright © 2004-2010 Joe Kucera +// +// 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) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software +// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +// +// ----------------------------------------------------------------------------- +// DESCRIPTION: +// +// Background thread for automatic update of user details +// +// ----------------------------------------------------------------------------- + +#include "icqoscar.h" + +// Retrieve users' info +void CIcqProto::icq_InitInfoUpdate(void) +{ + // Create wait objects + hInfoQueueEvent = CreateEvent(NULL, FALSE, FALSE, NULL); + if (hInfoQueueEvent) { + // Init mutexes + infoUpdateMutex = new icq_critical_section(); + + // Init list + for (int i = 0; iEnter(); + + // Check if in list + for (i = 0; (iLeave(); + + return TRUE; + } + + return FALSE; +} + + +void CIcqProto::icq_DequeueUser(DWORD dwUin) +{ + if (nInfoUserCount > 0) + { + int nChecked = 0; + // Check if in list + infoUpdateMutex->Enter(); + for (int i = 0; (i < LISTSIZE && nChecked < nInfoUserCount); i++) + { + if (m_infoUpdateList[i].dwUin) + { + nChecked++; + // Remove from list + if (m_infoUpdateList[i].dwUin == dwUin) + { +#ifdef _DEBUG + NetLog_Server("Dequeued user %u", m_infoUpdateList[i].dwUin); +#endif + m_infoUpdateList[i].dwUin = 0; + m_infoUpdateList[i].hContact = NULL; + m_infoUpdateList[i].queued = 0; + nInfoUserCount--; + break; + } + } + } + infoUpdateMutex->Leave(); + } +} + + +void CIcqProto::icq_RescanInfoUpdate() +{ + bInfoPendingUsers = 0; + /* This is here, cause we do not want to emit large number of reuqest at once, + fill queue, and let thread deal with it */ + bInfoUpdateEnabled = 0; // freeze thread + + // Queue all outdated users + HANDLE hContact = FindFirstContact(); + while (hContact != NULL) + { + if (IsMetaInfoChanged(hContact)) + { // Queue user + if (!icq_QueueUser(hContact)) + { // The queue is full, pause queuing contacts + bInfoPendingUsers = 1; + break; + } + } + hContact = FindNextContact(hContact); + } + + bInfoUpdateEnabled = TRUE; +} + + +void CIcqProto::icq_EnableUserLookup(BOOL bEnable) +{ + bInfoUpdateEnabled = bEnable; + + // Notify worker thread + if (bInfoUpdateEnabled && hInfoQueueEvent) + SetEvent(hInfoQueueEvent); +} + + +void __cdecl CIcqProto::InfoUpdateThread( void* ) +{ + int i; + DWORD dwWait = WAIT_OBJECT_0; + + NetLog_Server("%s thread starting.", "Info-Update"); + + bInfoUpdateRunning = TRUE; + + while (bInfoUpdateRunning) + { + if (!nInfoUserCount && bInfoPendingUsers) // whole queue processed, check if more users needs updating + icq_RescanInfoUpdate(); + + if (!nInfoUserCount || !bInfoUpdateEnabled || !icqOnline()) + { + dwWait = WAIT_TIMEOUT; + while (bInfoUpdateRunning && dwWait == WAIT_TIMEOUT) + { // wait for new work or until we should end + dwWait = ICQWaitForSingleObject(hInfoQueueEvent, 10000); + } + } + if (!bInfoUpdateRunning) break; + + switch (dwWait) { + case WAIT_IO_COMPLETION: + // Possible shutdown in progress + break; + + case WAIT_OBJECT_0: + case WAIT_TIMEOUT: + // Time to check for new users + if (!bInfoUpdateEnabled) continue; // we can't send requests now + + if (nInfoUserCount && icqOnline()) + { + time_t now = time(NULL); + BOOL bNotReady = FALSE, bTimeOuted = FALSE; + + // Check the list, take only users that were there for at least 5sec + // wait if any user is there shorter than 5sec and not a single user is there longer than 20sec + infoUpdateMutex->Enter(); + for (i = 0; i= now) + bNotReady = TRUE; + } + } + infoUpdateMutex->Leave(); + + if (!bTimeOuted && bNotReady) + { + SleepEx(1000, TRUE); + if (!bInfoUpdateRunning) + { // need to end as fast as possible + NetLog_Server("%s thread ended.", "Info-Update"); + goto LBL_Exit; + } + continue; + } + + if (FindCookie(dwInfoActiveRequest, NULL, NULL)) + { // only send another request, when the previous is completed +#ifdef _DEBUG + NetLog_Server("Info-Update: Request 0x%x still in progress.", dwInfoActiveRequest); +#endif + SleepEx(1000, TRUE); + if (!bInfoUpdateRunning) + { // need to end as fast as possible + NetLog_Server("%s thread ended.", "Info-Update"); + goto LBL_Exit; + } + continue; + } + +#ifdef _DEBUG + NetLog_Server("Info-Update: Users %u in queue.", nInfoUserCount); +#endif + // Either some user is waiting long enough, or all users are ready (waited at least the minimum time) + m_ratesMutex->Enter(); + if (!m_rates) + { // we cannot send info request - icq is offline + m_ratesMutex->Leave(); + break; + } + WORD wGroup = m_rates->getGroupFromSNAC(ICQ_EXTENSIONS_FAMILY, ICQ_META_CLI_REQUEST); + while (m_rates->getNextRateLevel(wGroup) < m_rates->getLimitLevel(wGroup, RML_IDLE_30)) + { // we are over rate, need to wait before sending + int nDelay = m_rates->getDelayToLimitLevel(wGroup, RML_IDLE_50); + + m_ratesMutex->Leave(); +#ifdef _DEBUG + NetLog_Server("Rates: InfoUpdate delayed %dms", nDelay); +#endif + SleepEx(nDelay, TRUE); // do not keep things locked during sleep + if (!bInfoUpdateRunning) + { // need to end as fast as possible + NetLog_Server("%s thread ended.", "Info-Update"); + goto LBL_Exit; + } + m_ratesMutex->Enter(); + if (!m_rates) // we lost connection when we slept, go away + break; + } + if (!m_rates) + { // we cannot send info request - icq is offline + m_ratesMutex->Leave(); + break; + } + m_ratesMutex->Leave(); + + userinfo *hContactList[LISTSIZE]; + int nListIndex = 0; + BYTE *pRequestData = NULL; + int nRequestSize = 0; + + infoUpdateMutex->Enter(); + for (i = 0; iLeave(); + break; + } + if (!(dwInfoActiveRequest = sendUserInfoMultiRequest(pRequestData, nRequestSize, nListIndex))) + { // sending data packet failed + SAFE_FREE((void**)&pRequestData); + infoUpdateMutex->Leave(); + break; + } + SAFE_FREE((void**)&pRequestData); + + for (i = 0; idwUin = 0; + hContactList[i]->hContact = NULL; + hContactList[i]->queued = 0; + nInfoUserCount--; + } + infoUpdateMutex->Leave(); + } + break; + + default: + // Something strange happened. Exit + bInfoUpdateRunning = FALSE; + break; + } + } + + NetLog_Server("%s thread ended.", "Info-Update"); + +LBL_Exit: + SAFE_DELETE(&infoUpdateMutex); + CloseHandle(hInfoQueueEvent); +} + +// Clean up before exit +void CIcqProto::icq_InfoUpdateCleanup(void) +{ + NetLog_Server("%s must die.", "Info-Update"); + bInfoUpdateRunning = FALSE; + if (hInfoQueueEvent) + SetEvent(hInfoQueueEvent); // break queue loop +} -- cgit v1.2.3