/* Copyright (C) 2000, 2001  SWsoft, Singapore
 *
 *  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., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 */

/*  $Id: squeue.cpp,v 1.43 2001/11/10 15:38:32 al Exp $
    Author : Alexander F. Avdonkin
	Implemented classes: CSiteUrls, CSitesQueue, CMySQLDatabaseI
*/

#include <sys/time.h>
#include "squeue.h"
#include "charsets.h"
#include "sqldb.h"
#include "parse.h"
#include "hrefs.h"
#include "rank.h"
#include "index.h"
#include "config.h"
#include "logger.h"
#include "lastmod.h"
//#include "geo.h"

hash_set<CURLName> Sites;
CMapStringToStringVec Robots;

void CSiteUrls::SetLastAccess()
{
	if (m_minDelay)
	{
		gettimeofday(&m_lastAccess, NULL);
	}
}

int CSiteUrls::WillBeReady()
{
	if (m_minDelay)
	{
		double d;
		struct timeval tm;
		gettimeofday(&tm, NULL);
		d = m_minDelay - timedif(tm, m_lastAccess);
		return d > 0 ? (int)(d * 1000) + 1 : 0;
	}
	else
	{
		return 0;
	}
}

void CSitesQueue::Insert(CSiteUrls* urls)
{
	if (m_current == NULL)
	{
		m_current = urls;
		urls->m_next = urls;
		urls->m_prev = urls;
	}
	else
	{
		urls->m_next = m_current;
		urls->m_prev = m_current->m_prev;
		m_current->m_prev->m_next = urls;
		m_current->m_prev = urls;
	}
}

void CSitesQueue::AddURL(ULONG site_id, ULONG url_id, CSQLDatabase* database)
{
	CSiteUrls* urls;
	iterator it = find(site_id);
	if (it == end())
	{
		CServer* srv=NULL;
		char site[300];
		if (database->GetSite(site_id, site)) srv = FindServer(site);
		urls = &(*this)[site_id];
		urls->m_siteID = site_id;
		if (srv)
		{
			urls->m_minDelay = srv->m_minDelay;
			urls->m_maxDocs = srv->m_maxDocs;
		}
		m_inactiveSize++;
		Insert(urls);
	}
	else
	{
		urls = &it->second;
		if ((urls->m_count == 0) && (urls->m_state == 0))
		{
			m_inactiveSize++;
			m_failedConns += urls->m_connFailed;
			Insert(urls);
		}
	}
	urls->Insert(url_id);
	m_qDocs++;
}

void CSitesQueue::AddURL(ULONG site_id, ULONG url_id, const char* url)
{
	CSiteUrls* urls;
	iterator it = find(site_id);
	if (it == end())
	{
		CServer* srv;
		srv = url ? FindServer(url) : NULL;
		urls = &(*this)[site_id];
		urls->m_siteID = site_id;
		if (srv) urls->m_minDelay = srv->m_minDelay;
		m_inactiveSize++;
		Insert(urls);
	}
	else
	{
		urls = &it->second;
		if ((urls->m_count == 0) && (urls->m_state == 0))
		{
			m_inactiveSize++;
			m_failedConns += urls->m_connFailed;
			Insert(urls);
		}
	}
	urls->Insert(url_id);
	m_qDocs++;
}

ULONG CSitesQueue::ExtractURL()
{
	if (m_current)
	{
		int ms;
		if ((ms = m_current->WillBeReady()) != 0)
		{
			m_current = m_current->m_next;
			return ~0;
		}
		CSiteUrls* urls = m_current->Remove();
		m_current = m_current->m_next == m_current ? NULL : m_current->m_next;
		m_inactiveSize--;
		m_activeSize++;
		urls->m_state = 1;
		return urls->RemoveFirst();
	}
	else
	{
		return 0;
	}
}

void CSitesQueue::DeleteURL(ULONG siteID, int index_result)
{
	CSiteUrls& urls = (*this)[siteID];
	m_activeSize--;
	urls.m_state = 0;
	int lastFailed = urls.m_connFailed;
	urls.m_connFailed = (index_result == NET_CANT_CONNECT) || (index_result == NET_CANT_RESOLVE) ? 1 : 0;
	if (urls.m_count != 0)
	{
		m_inactiveSize++;
		m_failedConns += (urls.m_connFailed - lastFailed);
		if ((++urls.m_docCnt >= urls.m_maxDocs) || (index_result < 0))
		{
			urls.m_docCnt = 0;
			Insert(&urls);
		}
		else
		{
			Insert(&urls);
			m_current = m_current->m_prev;
		}
	}
	else
	{
		m_failedConns -= lastFailed;
//		urls.m_connFailed = 0;
	}
	urls.SetLastAccess();
	m_qDocs--;
}

