/***************************************************************************
                HotContentInfo.cpp
                -----------------------------------------
    begin      : 2011/11/24
    copyright  : (C) 2005 SolutionBox Inc.
    author     : Service 1 Team
    email      : svc1@solbox.com
    version    : 1.0

    CopyRight(C) 2005 SolutionBox Inc. All Rights reserved.
    Redistribution and use in source and binary forms, with or with out
    modification, are not permitted in outside of SolutionBox Inc.
***************************************************************************/
#include "HotContentInfoMap.h"
#include "Logger.h"
#include "DaemonConfigs.h"
#include "MutexLock.hpp"

#define		REQUEST_TIME_OVER_SEC		180

////////////////////////////////////////////////////////////////////////////
// CHotContentData Class
////////////////////////////////////////////////////////////////////////////
CHotContentData::CHotContentData( std::string filename, int nFdCount )
{
	m_szFilename			= filename;
	m_timeLastReq			= time(0);
	m_timeLastUpdate    	= m_timeLastReq;
	m_nFdCount	= nFdCount;

	m_updateExpire = CDeamonConfig::GetInstance()->GetContentExpireSec();
	pthread_mutex_init(&m_mutex, NULL);
}

CHotContentData::~CHotContentData()
{
	ProtectedMutex mutex(m_mutex);
	pthread_mutex_destroy(&m_mutex);
}

void CHotContentData::UpdateRequestTime()
{
	ProtectedMutex mutex(m_mutex);
	/// 요청 시간 변경.
	m_timeLastReq = time(0);
}

void CHotContentData::UpdateInfo(int nFdCount)
{
	ProtectedMutex mutex(m_mutex);
	/// 수정 시간 변경.
	m_timeLastUpdate = time(0);
    m_nFdCount = nFdCount;
}

bool CHotContentData::IsIncrease(int nFdCount)
{
	ProtectedMutex mutex(m_mutex);
    return (m_nFdCount < nFdCount) ? true : false;
}

bool CHotContentData::IsExipireTimeout()
{
	ProtectedMutex mutex(m_mutex);
	/// m_timeLastUpdate 기준으로 timeout을 정한다.
	if ((time(0) - m_timeLastUpdate) >  m_updateExpire)
	{
		LOG( LDBG, "Hot content data timeout. file=%s", GetFilename().c_str() );
		return true;
	}
    
	return false;
}

bool CHotContentData::IsReqTimeOver()
{
	ProtectedMutex mutex(m_mutex);
	/// m_timeLastUpdate 기준으로 timeout을 정한다.
	if( ( time(0) - m_timeLastReq ) > REQUEST_TIME_OVER_SEC )
	{
		LOG( LDBG, "Not rquest timeout. file=%s", GetFilename().c_str() );
		return true;
	}
    
	return false;
}

////////////////////////////////////////////////////////////////////////////
// CHotContentInfoMap Class
////////////////////////////////////////////////////////////////////////////
CHotContentInfoMap::CHotContentInfoMap()
{
	// CHG 2020-07-20 huibong internal cache 관련 fd 감시 on/off 관련 기능 개선 (#33112)
	//                - 설정 관련 잘못 맵핑된 버그 수정
	//m_nMaxSize = CDeamonConfig::GetInstance()->GetContentExpireSec();
	m_nMaxSize = CDeamonConfig::GetInstance()->GetContentMaxInfo();

	pthread_mutex_init(&m_mutex, NULL);
}

CHotContentInfoMap::~CHotContentInfoMap()
{
	ProtectedMutex mutex(m_mutex);
	m_mapHotContentInfo.clear();
	pthread_mutex_destroy(&m_mutex);
}

bool CHotContentInfoMap::IsOverflow()
{
	ProtectedMutex mutex(m_mutex);
	bool r = ((int)m_mapHotContentInfo.size() >= m_nMaxSize) ? true : false;
	return r;
}

CHotContentData* CHotContentInfoMap::GetData( std::string szFilename )
{
	FUNC_BEGIN();
	ProtectedMutex mutex(m_mutex);
	if( szFilename.empty() == true )
	{
		LOG( LWAR, "Input parameter filename is empty." );
		FUNC_END();
		return NULL;
	}
    
	map<string, CHotContentData>::iterator it;
    
	it = m_mapHotContentInfo.find( szFilename );
    
	if( it == m_mapHotContentInfo.end() )
	{
		LOG( LDBG, "No have this file information. filename=[%s]", szFilename.c_str() );
		FUNC_END();
		return NULL;
	}
    
	FUNC_END();
    
	return &(it->second);
}

bool CHotContentInfoMap::AddData( std::string szFileName, int nFdCount )
{
	FUNC_BEGIN();
	
    CHotContentData data(szFileName, nFdCount);
    // 1. 지정한 maxsize 보다 큰가?
	if( IsOverflow() == true )
	{
		_LOG(LWAR, "Add failed. Because this map is full. Currunt MapSize = %zu, MaxSize = %d Filename=%s",
							 m_mapHotContentInfo.size(), m_nMaxSize, data.GetFilename().c_str() );
		FUNC_END();
		return false;
	}
	
	ProtectedMutex mutex(m_mutex);
	// 2. 맵에 추가한다.
	pair< map<string, CHotContentData>::iterator, bool > itRet;
	itRet = m_mapHotContentInfo.insert( map<string, CHotContentData>::value_type( data.GetFilename(), data ) );
	if( itRet.second == false )
	{
		_LOG( LWAR, "Add failed. May be already exist this file. filename = %s", data.GetFilename().c_str() );
		FUNC_END();
		return false;
	}

	_LOG( LINF, "Added this file = %s", data.GetFilename().c_str() );

	FUNC_END();

	return true;
}

void CHotContentInfoMap::Arrangement()
{
	FUNC_BEGIN();
	ProtectedMutex mutex(m_mutex);
	map<string, CHotContentData>::iterator it;
	for( it = m_mapHotContentInfo.begin(); it != m_mapHotContentInfo.end(); )
	{
		if( it->second.IsExipireTimeout() == true )
		{
			_LOG( LINF, "Arrangement(Delete) data. file=%s", it->second.GetFilename().c_str() );
			m_mapHotContentInfo.erase( it++ );
		} 
		else 
		{
			++it;
		}
	}
    
	FUNC_END();
}
