/*
 * cleaner.cc
 *
 *  Created on: 05.02.2011
 *      Author: ed
 */

#include "debug.h"
#include "meta.h"

#include "cleaner.h"

#include "fileitem.h"
#include "acfg.h"
#include "caddrinfo.h"
#include "tcpconnect.h"

#include <limits>
#include <cstring>
using namespace MYSTD;

cleaner g_victor;

cleaner::cleaner() : m_thr(0), m_bTerminating(false)
{
	m_nextRun = END_OF_TIME;
}

void cleaner::WorkLoop()
{
	LOGSTART("cleaner::Do");

	for(;;)
	{
		time_t now(time(0));

		{
			setLockGuard;
			if(m_bTerminating)
				return;

			if(now < m_nextRun)
			{
				time_t rem=m_nextRun-now;
				wait(rem, 123);
				if(m_bTerminating)
					return;
				continue;
			}
			m_nextRun = END_OF_TIME;
			// can do the work now...
		}

		time_t nextTimeProposal = fileitem::DoDelayedUnregAndCheck();
		time_t nextTimeCand = min(nextTimeProposal, END_OF_TIME);
		nextTimeProposal = acfg::ExecutePostponed();
		nextTimeCand = min(nextTimeProposal, nextTimeCand);
		nextTimeProposal = CAddrInfo::ExpireCache();
		nextTimeCand = min(nextTimeProposal, nextTimeCand);
		nextTimeProposal = tcpconnect::ExpireCache();
		nextTimeCand = min(nextTimeProposal, nextTimeCand);


		{
			setLockGuard;
			if(m_bTerminating)
				return;
			// considering case where some other thread has set a lower value in the meantime
			m_nextRun = min(m_nextRun, nextTimeCand);
		}
	};
}

cleaner::~cleaner()
{
}


inline void * CleanerThreadAction(void *pVoid)
{
	static_cast<cleaner*>(pVoid)->WorkLoop();
	return NULL;
}

void cleaner::RunLatestAt(time_t when)
{
	setLockGuard;
	if(m_thr == 0)
		pthread_create(&m_thr, NULL, CleanerThreadAction, (void *)this);

	if(when < m_nextRun)
	{
		m_nextRun = when;
		notifyAll();
	}
}

void cleaner::Stop()
{
	{
		setLockGuard;

		if(!m_thr)
			return;

		m_bTerminating = true;
		m_nextRun = 1;
		notifyAll();
	}
    pthread_join(m_thr, NULL);
    m_thr = 0;
    m_bTerminating=false;
}
